Android開(kāi)發(fā)仿QQ空間根據(jù)位置彈出PopupWindow顯示更多操作效果
我們打開(kāi)QQ空間的時(shí)候有個(gè)箭頭按鈕點(diǎn)擊之后彈出PopupWindow會(huì)根據(jù)位置的變化顯示在箭頭的上方還是下方,比普通的PopupWindow彈在屏幕中間顯示好看的多。
先看QQ空間效果圖:
這個(gè)要實(shí)現(xiàn)這個(gè)效果可以分幾步進(jìn)行
1.第一步自定義PopupWindow,實(shí)現(xiàn)如圖的樣式,這個(gè)繼承PopupWindow自定義布局很容易實(shí)現(xiàn)
2.得到點(diǎn)擊按鈕的位置,根據(jù)位置是否在屏幕的中間的上方還是下方,將PopupWindow顯示在控件的上方或者下方
3.適配問(wèn)題,因?yàn)镻opupWindow上面的操作列表是動(dòng)態(tài)的所以要自定義listView
4.動(dòng)畫(huà)效果+背景變暗
通過(guò)步驟分析,我們就很清晰的了解我們要做什么,話不多說(shuō),從第一步開(kāi)始吧
下面自定義PopupWindow實(shí)現(xiàn)效果
1.重寫(xiě)listView,重新計(jì)算高度(一般也應(yīng)用于解決ScrollView嵌套listView只顯示一行的問(wèn)題)
public class MyListView extends ListView { public MyListView(Context context, AttributeSet attrs) { super(context, attrs); } public MyListView(Context context) { super(context); } public MyListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST)); } }
2.自定義PopupWindow的布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="right"> <ImageView android:id="@+id/arrow_up" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="28dp" android:src="@drawable/arrow_up_white" android:visibility="visible"/> <com.widget.MyListView android:id="@+id/lv_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/normal_margin8" android:layout_marginTop="-1dp" android:layout_marginBottom="-1dp" android:dividerHeight="0dp" android:layout_marginLeft="@dimen/normal_margin8" android:layout_marginRight="@dimen/normal_margin8" android:scrollbars="none" android:background="@drawable/custom_white" android:divider="@null"></com.widget.MyListView> <ImageView android:id="@+id/arrow_down" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="28dp" android:src="@drawable/arrow_down_white" android:visibility="visible"/> </LinearLayout>
2.PopupWindow彈出動(dòng)畫(huà)以及消失動(dòng)畫(huà)
popshow_operation_anim_down.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <scale android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:fromXScale="0.0" android:toXScale="1.0" android:fromYScale="0.0" android:toYScale="1.0" android:pivotX="90%" android:pivotY="0%" android:fillAfter="false" android:duration="300" > </scale> </set>
popshow_operation_anim_up.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <scale android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:fromXScale="0.0" android:toXScale="1.0" android:fromYScale="0.0" android:toYScale="1.0" android:pivotX="90%" android:pivotY="100%" android:fillAfter="false" android:duration="250" > </scale> </set>
消失動(dòng)畫(huà)是漸隱動(dòng)畫(huà)可以自己定義,同理。
3.重寫(xiě)PopupWindow了
public class CustomOperationPopWindow extends PopupWindow { private Context context; private View conentView; private View backgroundView; private Animation anim_backgroundView; private MyListView listView; private TypeSelectPopuAdapter selectAdapter; ImageView arrow_up, arrow_down; List<TypeSelect> typeSelectlist = new ArrayList<>(); int[] location = new int[2]; private OnItemListener onItemListener; private AdapterView.OnItemClickListener onItemClickListener; public interface OnItemListener { public void OnItemListener(int position, TypeSelect typeSelect); } ; public void setOnItemMyListener(OnItemListener onItemListener) { this.onItemListener = onItemListener; } public CustomOperationPopWindow(Context context) { this.context = context; initView(); } public CustomOperationPopWindow(Context context, List<TypeSelect> typeSelectlist) { this.context = context; this.typeSelectlist = typeSelectlist; initView(); } private void initView() { this.anim_backgroundView = AnimationUtils.loadAnimation(context, R.anim.alpha_show_anim); LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.conentView = inflater.inflate(R.layout.view_operation_popupwindow, null); // 設(shè)置SelectPicPopupWindow的View this.setContentView(conentView); // 設(shè)置SelectPicPopupWindow彈出窗體的寬 this.setWidth(LayoutParams.MATCH_PARENT); // 設(shè)置SelectPicPopupWindow彈出窗體的高 this.setHeight(LayoutParams.WRAP_CONTENT); // 設(shè)置SelectPicPopupWindow彈出窗體可點(diǎn)擊 this.setFocusable(true); this.setOutsideTouchable(true); // 刷新?tīng)顟B(tài) this.update(); // 實(shí)例化一個(gè)ColorDrawable顏色為半透明 ColorDrawable dw = new ColorDrawable(0000000000); // 點(diǎn)back鍵和其他地方使其消失,設(shè)置了這個(gè)才能觸發(fā)OnDismisslistener ,設(shè)置其他控件變化等操作 this.setBackgroundDrawable(dw); // 設(shè)置SelectPicPopupWindow彈出窗體動(dòng)畫(huà)效果 this.setAnimationStyle(R.style.operation_popwindow_anim_style_up); this.listView = (MyListView) conentView.findViewById(R.id.lv_list); this.arrow_up = (ImageView) conentView.findViewById(R.id.arrow_up); this.arrow_down = (ImageView) conentView.findViewById(R.id.arrow_down); //設(shè)置適配器 this.selectAdapter = new TypeSelectPopuAdapter(context, typeSelectlist, R.layout.item_operation_popu); this.listView.setAdapter(selectAdapter); this.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (isShowing()) { dismiss(); } onItemListener.OnItemListener(position, typeSelectlist.get(position)); } }); this.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss() { if (backgroundView != null) { backgroundView.setVisibility(View.GONE); } } }); } //設(shè)置數(shù)據(jù) public void setDataSource(List<TypeSelect> typeSelectlist) { this.typeSelectlist = typeSelectlist; this.selectAdapter.notifyDataSetChanged(); } /** * 沒(méi)有半透明背景 顯示popupWindow * * @param */ public void showPopupWindow(View v) { v.getLocationOnScreen(location); //獲取控件的位置坐標(biāo) //獲取自身的長(zhǎng)寬高 conentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); if (location[1] > MainApplication.SCREEN_H / 2 + 100) { //MainApplication.SCREEN_H 為屏幕的高度,方法可以自己寫(xiě) this.setAnimationStyle(R.style.operation_popwindow_anim_style_up); arrow_up.setVisibility(View.GONE); arrow_down.setVisibility(View.VISIBLE); this.showAtLocation(v, Gravity.NO_GRAVITY, (location[0]), location[1] - conentView.getMeasuredHeight()); } else { this.setAnimationStyle(R.style.operation_popwindow_anim_style_down); arrow_up.setVisibility(View.VISIBLE); arrow_down.setVisibility(View.GONE); this.showAsDropDown(v, 0, 0); } } /** * 攜帶半透明背景 顯示popupWindow * * @param */ public void showPopupWindow(View v, View backgroundView) { this.backgroundView = backgroundView; v.getLocationOnScreen(location); //獲取控件的位置坐標(biāo) //獲取自身的長(zhǎng)寬高 conentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); backgroundView.setVisibility(View.VISIBLE); //對(duì)view執(zhí)行動(dòng)畫(huà) backgroundView.startAnimation(anim_backgroundView); if (location[1] > MainApplication.SCREEN_H / 2 + 100) { //若是控件的y軸位置大于屏幕高度的一半,向上彈出 this.setAnimationStyle(R.style.operation_popwindow_anim_style_up); arrow_up.setVisibility(View.GONE); arrow_down.setVisibility(View.VISIBLE); this.showAtLocation(v, Gravity.NO_GRAVITY, (location[0]), location[1] - conentView.getMeasuredHeight()); //顯示指定控件的上方 } else { this.setAnimationStyle(R.style.operation_popwindow_anim_style_down); //反之向下彈出 arrow_up.setVisibility(View.VISIBLE); arrow_down.setVisibility(View.GONE); this.showAsDropDown(v, 0, 0); //顯示指定控件的下方 } } /** * 顯示popupWindow 根據(jù)特殊要求高度顯示位置 * * @param */ public void showPopupWindow(View v, View backgroundView,int hight) { this.backgroundView = backgroundView; v.getLocationOnScreen(location); //獲取自身的長(zhǎng)寬高 conentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); backgroundView.setVisibility(View.VISIBLE); //對(duì)view執(zhí)行動(dòng)畫(huà) backgroundView.startAnimation(anim_backgroundView); if (location[1] > MainApplication.SCREEN_H / 2 + 100) { this.setAnimationStyle(R.style.operation_popwindow_anim_style_up); arrow_up.setVisibility(View.GONE); arrow_down.setVisibility(View.VISIBLE); this.showAtLocation(v, Gravity.NO_GRAVITY, (location[0]), location[1] - conentView.getMeasuredHeight()-hight); } else { this.setAnimationStyle(R.style.operation_popwindow_anim_style_down); arrow_up.setVisibility(View.VISIBLE); arrow_down.setVisibility(View.GONE); this.showAsDropDown(v, 0, 0); } } }
4.代碼中的用法
1.
CustomOperationPopWindow customOperationPopWindow = new CustomOperationPopWindow(this, operationTypeSelectlist); customOperationPopWindow.setOnItemMyListener(new CustomOperationPopWindow.OnItemListener() { @Override public void OnItemListener(int position, TypeSelect typeSelect) { //此處實(shí)現(xiàn)列表點(diǎn)擊所要進(jìn)行的操作 } });
2.
textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { customOperationPopWindow.showPopupWindow(textView);//可以傳個(gè)半透明view v_background過(guò)去根據(jù)業(yè)務(wù)需要顯示隱藏 } });
5.最終實(shí)際效果
以上代碼為幾乎主要全部代碼,主要是PopupWindow的用法,思路清晰一步一步實(shí)現(xiàn)很簡(jiǎn)單。
以上所述是小編給大家介紹的Android開(kāi)發(fā)仿QQ空間根據(jù)位置彈出PopupWindow顯示更多操作效果,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Android?flutter?Dio鎖的巧妙實(shí)現(xiàn)方法示例
這篇文章主要為大家介紹了Android?flutter?Dio鎖的巧妙實(shí)現(xiàn)方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Android實(shí)現(xiàn)計(jì)時(shí)器功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)計(jì)時(shí)器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04Android四大組件:Activity/Service/Broadcast/ContentProvider作用示例
Android是一種基于Linux,自由及開(kāi)放源代碼的操作系統(tǒng),Android分為四個(gè)層,從高層到底層分別是應(yīng)用程序?qū)?、?yīng)用程序框架層、系統(tǒng)運(yùn)行庫(kù)層和Linux內(nèi)核層,Android有四大基本組件:Activity、Service服務(wù)、BroadcastReceiver廣播接收器、Content Provider內(nèi)容提供者2023-11-11Android實(shí)現(xiàn)史上最簡(jiǎn)單自定義開(kāi)關(guān)按鈕的方法
在平常的開(kāi)發(fā)中按鈕是經(jīng)常使用到的控件之一,下面這篇文章主要給大家介紹了關(guān)于Android實(shí)現(xiàn)史上最簡(jiǎn)單自定義開(kāi)關(guān)按鈕的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04Android實(shí)現(xiàn)斷點(diǎn)多線程下載
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)斷點(diǎn)多線程下載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12