帝都幾日降溫,終於被撂倒了。but 只要一息尚存就得不斷進步!因而,寫出 《PopupWindow 使用詳解》的第二篇 筆記,先奉上 第一篇連接: 《PopupWindow 使用詳解(一) 中文API 文檔 贈送 ListPopupWindow 中文 API》。下面給你們展現一下製做的效果gif。android
PopupWindow 效果演示git
下面進行一個樣式一個樣式的肢解哈,對了,全部效果筆者都沒有製做載入動畫和退出動畫。有須要的小夥伴能夠經過 這個方法 public void setAnimationStyle(int animationStyle)
進行設置,也是很簡單、很經常使用的。程序員
照片選取樣圖github
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_pic" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/shape_pic_select" android:gravity="bottom" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginEnd="5dp" android:orientation="vertical"> <Button android:id="@+id/btn_pic_photo" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="1dp" android:background="#ffffff" android:text="相 冊" android:textColor="#3c3c3c" android:textSize="16sp" /> <Button android:id="@+id/btn_pic_camera" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="1dp" android:background="#ffffff" android:text="拍 照" android:textColor="#3c3c3c" android:textSize="16sp" /> <Button android:id="@+id/btn_pic_cancel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="1dp" android:background="#ffffff" android:text="取 消" android:textColor="#3c3c3c" android:textSize="16sp" /> </LinearLayout> </LinearLayout>
/** * 照片選擇器 */ @SuppressLint("InflateParams") private void showPicSelect() { view = LayoutInflater.from(this).inflate(R.layout.item_pic_select, null, false); LinearLayout llPop = view.findViewById(R.id.ll_pic); Button btnCamera = view.findViewById(R.id.btn_pic_camera); Button btnPhoto = view.findViewById(R.id.btn_pic_photo); Button btnCancel = view.findViewById(R.id.btn_pic_cancel); btnCamera.setOnClickListener(this); btnPhoto.setOnClickListener(this); btnCancel.setOnClickListener(this); llPop.setOnClickListener(this); myPop = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); myPop.setBackgroundDrawable(new ColorDrawable()); myPop.showAtLocation(rlMain, Gravity.BOTTOM, 0, 0); } @Override public void onBackPressed() { if (myPop.isShowing()) { myPop.dismiss(); } else { super.onBackPressed(); } }
以前筆者看了看網上百度來的答案,實現陰影效果的思路大概是,當 PopupWindow 彈出時將 Activity 設置爲半透明,可是這種思路的弊端是 Activity 透明瞭,你懂得,你能夠在 A Activity 界面直接看到了 桌面或者是 B Activity 界面的東西,很蛋疼。
筆者的思路是:爲 PopupWindow 設置一個半透明的背景色,而後監聽這不背景 layout 的點擊事件,和物理鍵的返回事件。不然會出現點擊無效果的現象。具體邏輯如上。微信
效果展現app
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/ll_qq" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:background="@drawable/shape_qq" android:orientation="horizontal" tools:ignore="UselessParent"> <TextView android:id="@+id/tv_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" android:text="刪除" android:textColor="#ffffff" android:textSize="16sp" /> <View android:layout_width="2dp" android:layout_height="match_parent" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:background="#666666" /> <TextView android:id="@+id/tv_be_top" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" android:text="置頂" android:textColor="#ffffff" android:textSize="16sp" /> </LinearLayout> <ImageView android:id="@+id/iv_three" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/ll_qq" android:layout_centerHorizontal="true" android:background="@null" android:layout_marginTop="-5dp" android:contentDescription="@string/app_name" android:src="@mipmap/ic_three" /> </RelativeLayout>
/** * 仿qq 產生水滴按鈕 */ @SuppressLint("InflateParams") private void showQq() { view = LayoutInflater.from(this).inflate(R.layout.item_qq, null, false); TextView tvTop = view.findViewById(R.id.tv_be_top); TextView tvDelete = view.findViewById(R.id.tv_delete); tvDelete.setOnClickListener(this); tvTop.setOnClickListener(this); myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); myPop.setBackgroundDrawable(new ColorDrawable()); myPop.setOutsideTouchable(true); myPop.getContentView().measure(0, 0); myPop.showAsDropDown(cvMain, (cvMain.getWidth() - myPop.getContentView().getMeasuredWidth()) / 2, -(cvMain.getHeight() + myPop.getContentView().getMeasuredHeight())); }
這個其實沒什麼好說的,可是須要注意的兩點是:(1)、ui 必定要有的或者是本身會個ps 也行,仔細看筆者佈局,有一個地方,設置 margin 屬性竟然用了 負值 不然沒法保證 下面的shape 背景與三角標進行無縫銜接;(2)、注意這個方法必定要設置即使是不設置值 public void setBackgroundDrawable(Drawable background)
不然會致使 public void setOutsideTouchable(boolean touchable)
這個方法不起做用,即出現點擊 PopupWindow 外部區域沒法隱藏 PopupWindow 的尷尬局面框架
圖片輪播效果less
<!--佈局 1--> <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" app:cardCornerRadius="10dp"> <android.support.v4.view.ViewPager android:id="@+id/vp_pop" android:layout_width="200dp" android:layout_height="300dp" android:background="#48BAFF" /> </android.support.v7.widget.CardView> <!--佈局 2--> <?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:gravity="center" android:orientation="vertical"> <ImageView android:layout_width="200dp" android:layout_height="300dp" android:contentDescription="@string/app_name" android:src="@mipmap/pic_1" /> </LinearLayout>
/** * 輪播效果 */ @SuppressLint("InflateParams") private void showPager() { views = new ArrayList<>(); view = LayoutInflater.from(this).inflate(R.layout.item_pager, null, false); ViewPager vpPop = view.findViewById(R.id.vp_pop); picView01 = LayoutInflater.from(this).inflate(R.layout.item_pop_vp_01, null, false); picView02 = LayoutInflater.from(this).inflate(R.layout.item_pop_vp_02, null, false); picView03 = LayoutInflater.from(this).inflate(R.layout.item_pop_vp_03, null, false); picView04 = LayoutInflater.from(this).inflate(R.layout.item_pop_vp_04, null, false); views.add(picView01); views.add(picView02); views.add(picView03); views.add(picView04); vpPop.setAdapter(new MyPopAdapter()); myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); myPop.setOutsideTouchable(true); //懸浮效果 myPop.setElevation(5); myPop.setBackgroundDrawable(new ColorDrawable(0x00ffffff)); myPop.showAtLocation(rlMain, Gravity.CENTER, 0, 0); } /** * 配置 adapter */ class MyPopAdapter extends PagerAdapter { @Override public int getCount() { return views.size(); } @Override public boolean isViewFromObject(@NonNull View view, @NonNull Object o) { return view == o; } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { container.addView(views.get(position)); return views.get(position); } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { container.removeView(views.get(position)); } } @Override protected void onDestroy() { super.onDestroy(); if (views != null) { views.remove(picView01); views.remove(picView02); views.remove(picView03); views.remove(picView04); } if (myPop.isShowing()) { myPop.dismiss(); } }
首先,加載圖片須要進行相關處理,好比說用過Picasso 或者是 Glide 等框架,固然了也可將進行本身壓縮;ide
其次,因爲爲了突出美觀,筆者用了一個 CardView 能夠設置圓角,可是 CardView 的陰影屬性失效了,爲了凸顯層次感能夠設置 PopupWindow 的這個方法public void setElevation(float elevation)
該方法能夠是你感受出一種懸浮的效果;佈局
最後,沒用的 view 須要進行清理,不然會留在內存哦。
向下彈出效果
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/iv_beauty" android:layout_toEndOf="@+id/iv_beauty" android:src="@mipmap/ic_right" /> <ImageView android:id="@+id/iv_beauty" android:layout_width="150dp" android:layout_height="200dp" android:background="#669" android:src="@mipmap/pic_5" /> </RelativeLayout>
/** * 向下彈出 */ @SuppressLint("InflateParams") private void showDown() { view = LayoutInflater.from(this).inflate(R.layout.item_anywhere, null, false); myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); myPop.setBackgroundDrawable(new ColorDrawable()); myPop.setOutsideTouchable(true); myPop.getContentView().measure(0, 0); myPop.showAsDropDown(btnPopDown, -((myPop.getContentView().getMeasuredWidth() - btnPopDown.getWidth()) / 2), 0); }
這個沒什麼可說的了,和 上面 小標題二 相同 ,具體查看上方便可。
實現效果
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/iv_beauty" android:layout_toEndOf="@+id/iv_beauty" android:src="@mipmap/ic_right" /> <ImageView android:id="@+id/iv_beauty" android:layout_width="150dp" android:layout_height="200dp" android:background="#669" android:src="@mipmap/pic_5" /> </RelativeLayout>
/** * 向左彈出 */ @SuppressLint("InflateParams") private void showStart() { view = LayoutInflater.from(this).inflate(R.layout.item_pop_start, null, false); myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); myPop.setBackgroundDrawable(new ColorDrawable()); myPop.setOutsideTouchable(true); myPop.getContentView().measure(0, 0); myPop.showAsDropDown(fabStart, -(myPop.getContentView().getMeasuredWidth()), -(fabStart.getHeight() / 2 + myPop.getContentView().getMeasuredHeight())); }
這裏比較複雜的 就是 PopupWindow 的錨點位置 爲 其寄生的 控件的 左下角,而 Popwindow 的起始點爲 左上角,可是 PopupWindow 默認不超出界面。這就致使了 PopupWindow 明明在 控件則左側,可是卻沒法到達本身的想要位置。
因此 對於該現象,咱們只能 在計算偏移量的時候 須要向左 移動 (控件長度+PopupWindow的長度 +其餘長度)
效果展現
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" app:cardCornerRadius="10dp"> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#00000000" android:padding="10dp"> <TextView android:id="@+id/tv_name_p" android:layout_width="wrap_content" android:layout_height="40dp" android:gravity="center_vertical" android:text="帳戶:" android:textSize="16sp" /> <EditText android:layout_width="200dp" android:layout_height="40dp" android:layout_toEndOf="@+id/tv_name_p" android:background="@null" android:gravity="center_vertical" android:inputType="number" android:paddingStart="10dp" android:paddingEnd="10dp" android:singleLine="true" android:textSize="16sp" tools:text="123" /> <TextView android:id="@+id/tv_password_p" android:layout_width="wrap_content" android:layout_height="40dp" android:layout_below="@+id/tv_name_p" android:gravity="center_vertical" android:text="密碼:" android:textSize="16sp" /> <EditText android:layout_width="200dp" android:layout_height="40dp" android:layout_below="@+id/tv_name_p" android:layout_toEndOf="@+id/tv_password_p" android:background="@null" android:gravity="center_vertical" android:inputType="numberPassword" android:paddingStart="10dp" android:paddingEnd="10dp" android:singleLine="true" android:textSize="16sp" tools:text="123" /> </RelativeLayout> </android.support.v7.widget.CardView>
/** * 向右彈出 輸入框 */ @SuppressLint("InflateParams") private void showEnd() { view = LayoutInflater.from(this).inflate(R.layout.item_end_input, null, false); myPop = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); myPop.setBackgroundDrawable(new ColorDrawable(0x00ffffff)); myPop.setElevation(10); myPop.setOutsideTouchable(true); myPop.setFocusable(true); myPop.getContentView().measure(0, 0); myPop.showAsDropDown(fadEnd, (int) (fadEnd.getWidth() * 1.3), -((fadEnd.getHeight() + myPop.getContentView().getMeasuredHeight()) / 2)); }
這裏必定要 設置該方法 public void setFocusable(boolean focusable)
不然 在切換EditText 的時候只是光標進行了移動,可是 沒法召喚軟鍵盤。
一、筆者認爲,上面的大概能夠知足比較簡單的開發需求了,筆者很菜,這些已經足能夠知足筆者了目前;
二、關於偏移量這個會涉及導到一些小小的計算和一點點邏輯想法,因此不要只是作 cv 戰士,做爲文雅的程序員,咱們仍是須要有點本身的想法的哈;
三、代碼上傳 github 地址爲:PopupWindow
四、但願能夠幫到你,批評和建議,望各位大佬留言,小生在這裏謝過了。
做者:吾乃韓小呆 連接:https://www.jianshu.com/p/8e7b339d7a78 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。