PopupWindow 使用詳解(二) Popwindow 製做常見花哨效果

帝都幾日降溫,終於被撂倒了。but 只要一息尚存就得不斷進步!因而,寫出 《PopupWindow 使用詳解》的第二篇 筆記,先奉上 第一篇連接: 《PopupWindow 使用詳解(一) 中文API 文檔 贈送 ListPopupWindow 中文 API》。下面給你們展現一下製做的效果gif。android

PopupWindow 效果演示git


下面進行一個樣式一個樣式的肢解哈,對了,全部效果筆者都沒有製做載入動畫和退出動畫。有須要的小夥伴能夠經過 這個方法 public void setAnimationStyle(int animationStyle)進行設置,也是很簡單、很經常使用的。程序員

 

效果1、圖片選取功能(帶陰影)

照片選取樣圖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>

二、Java 邏輯代碼

/**
     * 照片選擇器
     */
    @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 的點擊事件,和物理鍵的返回事件。不然會出現點擊無效果的現象。具體邏輯如上。微信

2、仿qq和微信的長按置頂刪除功能

效果展現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>

二、Java 邏輯

/**
     * 仿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 的尷尬局面框架

3、實現懸浮圖片輪播

圖片輪播效果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>

二、Java 邏輯代碼

/**
     * 輪播效果
     */
    @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 須要進行清理,不然會留在內存哦。

4、向下彈出水滴效果

向下彈出效果

一、佈局源碼

<?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>

二、Java 邏輯

/**
     * 向下彈出
     */
    @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);
    }

三、注意事項

這個沒什麼可說的了,和 上面 小標題二 相同 ,具體查看上方便可。

5、實現屏幕右側向左彈出

實現效果

一、佈局代碼

<?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>

二、Java 邏輯代碼

/**
     * 向左彈出
     */
    @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的長度 +其餘長度)

6、實現須要獲取焦點的控件使用

效果展現

一、佈局代碼

<?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 的時候只是光標進行了移動,可是 沒法召喚軟鍵盤。

7、總結

一、筆者認爲,上面的大概能夠知足比較簡單的開發需求了,筆者很菜,這些已經足能夠知足筆者了目前;
二、關於偏移量這個會涉及導到一些小小的計算和一點點邏輯想法,因此不要只是作 cv 戰士,做爲文雅的程序員,咱們仍是須要有點本身的想法的哈;
三、代碼上傳 github 地址爲:PopupWindow
四、但願能夠幫到你,批評和建議,望各位大佬留言,小生在這裏謝過了。

做者:吾乃韓小呆 連接:https://www.jianshu.com/p/8e7b339d7a78 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。

相關文章
相關標籤/搜索