PopupWindow

简介: PopupWindow

概述


官方API


A popup window that can be used to display an arbitrary view. The popup window is a floating container that appears on top of the current activity.


一个弹出窗口控件,可以用来显示任意View,而且会浮动在当前activity的顶部


常用构造方法


一下仅列出本人认为常用的构造方法,全部构造方法(9个….)请查看官方文档。

  • 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是否显示焦点


常用方法


介绍几个用得较多的一些方法,其他的可自行查阅文档:


image.png

Code

效果图


20160312195840826.gif


res\anim\anim_pop.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha android:fromAlpha="0"
        android:toAlpha="1"
        android:duration="2000">
    </alpha>
</set> 


res\layout\item_popup.xml

android:background 是一张.9图片

<?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:background="@drawable/ic_pop_bg"
    android:orientation="vertical">
    <TextView
        android:id="@+id/textview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:text="选项一选项一选项一选项一选项一选项一"
        android:textSize="18sp" />
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#98FB98"
        />
    <TextView
        android:id="@+id/textview2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="5dp"
        android:text="选项二选项二选项二选项二选项二选项二"
        android:textSize="18sp" />
</LinearLayout>


PopupWindowAct.java

package com.turing.base.activity.popupWindowDemo;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import com.turing.base.R;
public class PopupWindowAct extends AppCompatActivity {
    private Context mContext;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_popup_window);
        mContext = PopupWindowAct.this;
    }
    public void showPopupWindow(View view){
        initPopWindow(view);
    }
    private void initPopWindow(View v) {
        // 将自定义布局转换为View
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_popup, null, false);
        TextView tv1 = (TextView) view.findViewById(R.id.textview1);
        TextView tv2 = (TextView) view.findViewById(R.id.textview2);
        //1.构造一个PopupWindow,参数依次是加载的View,宽高
        final PopupWindow popWindow = new PopupWindow(view,
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
        //设置加载动画
        popWindow.setAnimationStyle(R.anim.anim_pop);
        //这些为了点击非PopupWindow区域,PopupWindow会消失的,如果没有下面的
        //代码的话,你会发现,当你把PopupWindow显示出来了,无论你按多少次后退键
        //PopupWindow并不会关闭,而且退不出程序,加上下述代码可以解决这个问题
        popWindow.setTouchable(true);
        popWindow.setTouchInterceptor(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // 这里如果返回true的话,touch事件将被拦截
                // 拦截后 PopupWindow的onTouchEvent不被调用,这样点击外部区域无法dismiss
                return false;
            }
        });
        //要为popWindow设置一个背景才有效
        popWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));
        //设置popupWindow显示的位置,参数依次是参照View,x轴的偏移量,y轴的偏移量
        popWindow.showAsDropDown(v, 50, 0);
        //设置popupWindow里的按钮的事件
        tv1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(PopupWindowAct.this, "你点击了选项一~", Toast.LENGTH_SHORT).show();
            }
        });
        tv2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(PopupWindowAct.this, "你点击了选项二~", Toast.LENGTH_SHORT).show();
                popWindow.dismiss();
            }
        });
    }
}


其他

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的background,点击Back键或者点击弹窗的外部区域,弹窗就会dismiss.


相反,如果不设置PopupWindow的background,那么点击back键和点击弹窗的外部区域,弹窗是不会消失的.


 那么,如果我想要一个效果,点击外部区域,弹窗不消失,但是点击事件会向下面的activity传递,比如下面是一个WebView,我想点击里面的链接等.


 研究了半天,说是要给Window设置一个Flag,

WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL

看了源码,这个Flag的设置与否是由一个叫mNotTouchModal的字段控制,但是设置该字段的set方法被标记为@hide。

 所以要通过反射的方法调用:

 /**
     * Set whether this window is touch modal or if outside touches will be sent
     * to
     * other windows behind it.
     *
     */
    public static void setPopupWindowTouchModal(PopupWindow popupWindow,
            boolean touchModal) {
        if (null == popupWindow) {
            return;
        }
        Method method;
        try {
            method = PopupWindow.class.getDeclaredMethod("setTouchModal",
                    boolean.class);
            method.setAccessible(true);
            method.invoke(popupWindow, touchModal);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

然后在程序中:

setPopupWindowTouchModal(popupWindow, false);


该popupWindow外部的事件就可以传递给下面的Activity了。

参考Android PopupWindow的使用和分析

相关文章
|
7月前
|
API Android开发 容器
33. 【Android教程】悬浮窗:PopupWindow
33. 【Android教程】悬浮窗:PopupWindow
814 2
|
Android开发
ScrollView 与 ListView 以及 GridView 滑动冲突完美解决
ScrollView 与 ListView 以及 GridView 滑动冲突完美解决
|
XML 数据格式
DrawerLayout侧滑菜单、Toolbar和沉浸式状态栏的使用
DrawerLayout侧滑菜单、Toolbar和沉浸式状态栏的使用
Dialog和DialogFragment 设置背景透明
Dialog和DialogFragment 设置背景透明
1040 0
Snackbar使用详解
Snackbar使用详解
255 0
Snackbar使用详解
|
XML Android开发 数据格式
Snackbar详解
Snackbar是什么 Snackbar是Design Support Library库中的一个控件它是用来替代Toast的一个全新的控件,Snackbar与Toast最大的区别是Snackbar支持点击和滑动和滑动消失,如果用户没有进行操作它也会在到达指定时间后自动消失。
1602 0
|
Android开发
Android弹窗二则: PopupWindow和AlertDialog
前言 弹窗是图形界面必备的一个模块, 回忆一下windows那些恶心爆了的错误弹窗吧, 把弹窗制作的更高效友好一点是非常必要的. 这里说两个常用的弹窗类, PopupWindow和AlertDialog.
1156 0
|
XML Android开发 数据格式
ActionBar的使用
前言 山水一程,三生有幸。 启用ActionBar ActionBar需要在Android3.0以上的版本才能启用。如果希望关闭ActionBar,则可以设置该应用的主题为Xxxx.NoActionBar,配置如下。
1007 0