PopUpWindow 的使用筆記


最接做需求的時候,碰到了 PopUpWindow,但是也沒做過多了解,就是照搬別人的代碼改改邏輯。后面視覺看了之后,說讓我加一些動畫效果,使用起來更加舒服。可是我看別人以前也沒有寫,於是就開始搗鼓 PopUpWindow。同時也寫一篇文章記錄下,后續忘了也可以查看。

 

相關方法解讀

1)幾個常用的構造方法

我們在文檔中可以看到,提供給我們的PopupWindow的構造方法有九種之多,這里只貼實際 開發中用得較多的幾個構造方法:

  • public PopupWindow (Context context)

  • public PopupWindow(View contentView, int width, int height)

  • public PopupWindow(View contentView)

  • public PopupWindow(View contentView, int width, int height, boolean focusable)

參數就不用多解釋了吧,contentView是PopupWindow顯示的View,focusable是否顯示焦點

2)常用的一些方法

下面介紹幾個用得較多的一些方法,其他的可自行查閱文檔:

  • setContentView(View contentView):設置PopupWindow顯示的View

  • getContentView():獲得PopupWindow顯示的View

  • showAsDropDown(View anchor):相對某個控件的位置(正左下方),無偏移

  • showAsDropDown(View anchor, int xoff, int yoff):相對某個控件的位置,有偏移

  • showAtLocation(View parent, int gravity, int x, int y): 相對於父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以設置偏移或無偏移 PS:parent這個參數只要是activity中的view就可以了!

  • setWidth/setHeight:設置寬高,也可以在構造方法那里指定好寬高, 除了可以寫具體的值,還可以用WRAP_CONTENT或MATCH_PARENT, popupWindow的width和height屬性直接和第一層View相對應。

  • setFocusable(true):設置焦點,PopupWindow彈出后,所有的觸屏和物理按鍵都由PopupWindows 處理。其他任何事件的響應都必須發生在PopupWindow消失之后,(home 等系統層面的事件除外)。 比如這樣一個PopupWindow出現的時候,按back鍵首先是讓PopupWindow消失,第二次按才是退出 activity,准確的說是想退出activity你得首先讓PopupWindow消失,因為不並是任何情況下按back PopupWindow都會消失,必須在PopupWindow設置了背景的情況下 。

  • setAnimationStyle(int):設置動畫效果

創建布局

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:clipChildren="false"
    android:orientation="vertical">
    <View
        android:id="@+id/empty_view"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_weight="1"
        />

    <LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@color/colorPrimary"
        android:orientation="vertical"
        android:gravity="center_vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:text="test" />
        
    </LinearLayout>
</LinearLayout>

注意其中這行代碼:

android:layout_weight="1"

由於其他 view 沒有使用這個屬性,默認為0,使用該屬性的view將剩余的空間鋪滿。這樣就相當於為我們設置了一個蒙層了。

寫好布局后,需要將布局文件傳到容器中去。

 

PopUpWindow 使用

由於相關代碼比較長,直接附上完整代碼,方便大家查看。

完整代碼如下:

public class TestActivity extends AppCompatActivity implements View.OnClickListener {
    private PopupWindow mPopupWindow;
    private ViewGroup mContentView;
    private Button mBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        mBtn = (Button) findViewById(R.id.result);
        mPopupWindow = new PopupWindow(this);
        mPopupWindow.setContentView(getContentView(this));
        mPopupWindow.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
        mPopupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        mPopupWindow.setClippingEnabled(false);
        // 如果不設置PopupWindow的背景,有些版本就會出現一個問題:無論是點擊外部區域還是Back鍵都無法dismiss彈框
        mPopupWindow.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color
                .empty_view_background)));
        mPopupWindow.setOutsideTouchable(true);
        mPopupWindow.setFocusable(true);
        mPopupWindow.update();
        mBtn.setOnClickListener(this);
    }


    /**
     * popup window view 初始化
     *
     * @return View
     */
    private View getContentView(Context ctx) {
        mContentView = (ViewGroup) LayoutInflater.from(ctx)
                .inflate(R.layout.popup, null);
        View emptyViewAbovePanel = mContentView.findViewById(R.id.empty_view);
        emptyViewAbovePanel.setOnClickListener(this);
        return mContentView;
    }

    @Override
    public void onClick(View v) {
        int i = v.getId();
        if (i == R.id.empty_view) {
            Animation animation = AnimationUtils.loadAnimation(this, R.anim.pop_gone);
            mContentView.startAnimation(animation);
            animation.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    mPopupWindow.dismiss();
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
        } else if (i == R.id.result) {
            mContentView.startAnimation(AnimationUtils.loadAnimation(this, R.anim.pop_in));
            mPopupWindow.showAsDropDown(mBtn, 50, 50);
        }

    }
}

 上面的代碼設置了蒙層,出場入場的動畫效果。

 

動畫設置

出場動畫文件xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="400"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="0"
        android:toYDelta="100%" />
</set>

進場動畫文件xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="400"
        android:fromXDelta="0"
        android:fromYDelta="100%"
        android:toXDelta="0"
        android:toYDelta="0" />
</set>

 為什么出場動畫不用 PopUpWindow 默認動畫設置呢。這是因為視覺只希望下面藍色部分有動畫效果,蒙層不需要這個動畫效果。因此我們就必須添加額外的處理邏輯。如果采用默認的動畫設置效果,將會使得蒙層也有動畫效果。

在資源文件的values的style.xml中添加如下代碼

<style name="pop_animation" parent="android:Animation">
    <item name="android:windowEnterAnimation">@anim/pop_in</item>
    <item name="android:windowExitAnimation">@anim/pop_gone</item>
</style>

android:windowEnterAnimation:為窗體進入時執行;
android:windowExitAnimation:為窗體退出時執行;

將其使用到PopupWindow中:

mPopupWindow.setAnimationStyle(R.style.pop_animation);
mPopupWindow.showAtLocation(view, Gravity.CENTER, 0, 0);

setAnimationStyle() 即是為 PopupWindow 添加動畫的方法,由於 PopupWindow 不能像其他的 View 一樣使用 ObjectAnimator, 所以使用動畫需要在 style 中定義,並且使用 PopupWindow 的 setAnimationStyle() 方法。這樣的話就可以使用。

 

蒙層的處理

除了上面的我的蒙層方法,還有其他添加蒙層的方法:

1)添加一層view

private void addMaskView(IBinder token) {
    WindowManager.LayoutParams p = new WindowManager.LayoutParams();
    p.width = WindowManager.LayoutParams.MATCH_PARENT;
    p.height = WindowManager.LayoutParams.MATCH_PARENT;
    p.format = PixelFormat.TRANSLUCENT;
    p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
    p.token = token;
    p.windowAnimations = android.R.style.Animation_Toast;
    maskView = new View(context);
    maskView.setBackgroundColor(0x7f000000);
    maskView.setFitsSystemWindows(false);
    maskView.setOnKeyListener(new OnKeyListener() {
        @Override
        public boolean onKey(View v, int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                removeMaskView();
                return true;
            }
            return false;
        }
    });
    wm.addView(maskView, p);
}

然后在消失的時候進行移除:

public void dismiss() {
    if (maskView != null) {
        wm.removeViewImmediate(maskView);
        maskView = null;
    }
    super.dismiss();
}

2) 透明度

還有人是直接使用透明度來實現的。

private void bgAlpha(float alpha) {
    WindowManager.LayoutParams lp = ((Activity)context).getWindow().getAttributes();
    lp.alpha = alpha;// 0.0-1.0
    ((Activity)context).getWindow().setAttributes(lp);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM