Android之使用PopupWindow使用和总结

不废话,先爆照

Android之使用PopupWindow使用和总结_第1张图片

说明:

那个灰色背景是不能滑动里ListView里面的内容的

第一步:我们需要背景view

下面是我的background.xml文件
<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"
    tools:context=".HomeActivity"
    >

    <RelativeLayout
        android:id="@+id/rl_search_background"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:paddingTop="4dp"
        android:paddingBottom="4dp"
        android:paddingLeft="8dp"
        android:paddingRight="8dp">

        <RelativeLayout
            android:id="@+id/bt_nearby_search_background"
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:layout_centerInParent="true"
            android:background="@drawable/bg_search"
            android:padding="4dp"
            android:gravity="center">
            <Button
                android:id="@+id/btn_search_icon_background"
                android:layout_width="16dp"
                android:layout_height="16dp"
                android:layout_centerVertical="true"
                android:background="@mipmap/icon_search"
                android:clickable="false" />
            <EditText
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@+id/btn_search_icon_background"
                android:layout_centerVertical="true"
                android:layout_marginLeft="8dp"
                android:background="@null"
                android:textSize="12sp"
                android:hint="@string/search_hint"/>
        </RelativeLayout>
    </RelativeLayout>
</RelativeLayout>
design如下
Android之使用PopupWindow使用和总结_第2张图片

第二步:实现PopupWindow

/**
     * 点击评分,如果评分后,显示的弹出框
     */
    private void makePopupWindows() {
        View view = LayoutInflater.from(HomeActivity.this).inflate(
                R.layout.background, null);
        mPopupWindow = new PopupWindow(view, mScreenWidth, 600);
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.alpha = 0.5f;
        getWindow().setAttributes(params);
        mPopupWindow.setOutsideTouchable(true);
        mPopupWindow.setFocusable(true); // 设置PopupWindow可获得焦点
        mPopupWindow.setTouchable(true); // 设置PopupWindow可触摸
        mPopupWindow.showAsDropDown(background_button);
    }

如果你不理解下面三行代码的意思,你可以亲自去测试一下,分别设为true和false,会有什么效果
        mPopupWindow.setOutsideTouchable(true);
        mPopupWindow.setFocusable(true); // 设置PopupWindow可获得焦点
        mPopupWindow.setTouchable(true); // 设置PopupWindow可触摸

 PopUpWindow的焦点:

setFocusable设置PopupWindow的焦点,一般资料对此的解释都是:是否让Popupwindow可以点击但是这揭示了本质却与直观现象不符。实际上,
如果:
setFocusable(true);
则PopUpWindow本身可以看作一个类似于模态对话框的东西(但有区别),PopupWindow弹出后,所有的触屏和物理按键都有PopupWindows处理。其他任何事件的响应都必须发生在PopupWindow消失之后, (home  等系统层面的事件除外)。比如这样一个PopupWindow出现的时候,按back键首先是让PopupWindow消失,第二次按才是退出activity,准确的说是想退出activity你得首先让PopupWindow消失,因为不并是任何情况下按back  PopupWindow都会消失,必须在PopupWindow设置了背景的情况下 。
如果PopupWindow中有Editor的话,focusable要为true。
而setFocusable(false)
则PopUpWindow只是一个浮现在当前界面上的view而已,不影响当前界面的任何操作
是一个“没有存在感”的东西。
一般情况下setFocusable(true);
点击空白处的时候让PopupWindow消失


关于PopupWindow最搞笑的地方是setOutsideTouchable方法,原本以为如果你setOutsideTouchable(true)则点击PopupWindow之外的地方PopupWindow会消失,其实这玩意儿好像一点用都没有
要让点击PopupWindow之外的地方PopupWindow消失你需要调用setBackgroundDrawable(new BitmapDrawable());
设置背景,为了不影响样式,这个背景是空的。还可以这样写,觉得这样要保险些:
setBackgroundDrawable(new ColorDrawable(0x00000000));
背景不为空但是完全透明。如此设置还能让PopupWindow在点击back的时候消失。其实一直觉得很奇怪,不明白为什么一个背景会影响点击事件,只知道这样用可行。
后来在评论中有人回答了此问题:
如果有背景,则会在contentView外面包一层PopupViewContainer之后作为mPopupView,如果没有背景,则直接用contentView作为mPopupView。
而这个PopupViewContainer是一个内部私有类,它继承了FrameLayout,在其中重写了Key和Touch事件的分发处理

PopupWindow的动画

设置动画的方法:
在res/value/styles.xml添加一个sytle
style name="anim_menu_bottombar">
    <item name="android:windowEnterAnimation">@anim/menu_bottombar_in</item>
    <item name="android:windowExitAnimation">@anim/menu_bottombar_out</item>
</style>
在工程res下新建anim文件夹,在anim文件夹先新建两个xml文件
menu_bottombar_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="250"
        android:fromYDelta="100.0%"
        android:toYDelta="0.0" />
</set>
menu_bottombar_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="250"
        android:fromYDelta="0.0"
        android:toYDelta="100%" />
</set>
mPopupWindow.setAnimationStyle(R.style.menu_anim_bottombar);

显示PopupWindow:

showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移
其实我发现showAtLocation的parent参数可以很随意,只要是activity中的view都可以。

第三步:怎么退出

pw.setFocusable(true),但是当我们这样设置之后,问题出现了,按返回键或者menu菜单键没有反应,怎么退出,请参考我之前的一篇博客
Android之如何解决popupWindow(pw.setFocusable(true))按返回键和menu键退出


最终我的代码如下
/**
     * 点击评分,如果评分后,显示的弹出框
     */
    private void makePopupWindows() {
        View view = LayoutInflater.from(HomeActivity.this).inflate(
                R.layout.background, null);
        mPopupWindow = new PopupWindow(view, mScreenWidth, 600);
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.alpha = 0.5f;
        getWindow().setAttributes(params);
        mPopupWindow.setOutsideTouchable(true);
        mPopupWindow.setFocusable(true); // 设置PopupWindow可获得焦点
        mPopupWindow.setTouchable(true); // 设置PopupWindow可触摸
        mPopupWindow.showAsDropDown(background_button);
        view.setFocusableInTouchMode(true);
        mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
        view.setOnKeyListener(new android.view.View.OnKeyListener() {
            public boolean onKey(View v, int keyCode, KeyEvent event) {
             // TODO Auto-generated method stub
                if (keyCode == KeyEvent.KEYCODE_BACK &&mPopupWindow.isShowing()) {
                    mPopupWindow.dismiss();
                    WindowManager.LayoutParams params= getWindow().getAttributes();
                    params.alpha=1.0f;
                    getWindow().setAttributes(params);
                    return true;
                }
                return false;
            }
        });
    }

只要设置监听函数调用这个函数就行




你可能感兴趣的:(android,PopupWindow)