怎么使点击一个popupwindow窗口之外的区域popupwindow消失呢?

这个功能应该是不难的,查了下文档,没发现明显的方法可以调用。


开始以为popupWindow.setOutsideTouchable(true);这个方法可以呢,试了试,不行,其实这个方法时设置popupWindow以外的区域可以相应触摸事件,比如我们重写了触摸事件去做一些别的操作。


对了,还有,设置popupWindow.setFocusable(true);  这样才能让popupWindow里面的布局控件获得点击的事件,否则就被它的父亲view给拦截了。


如果你想处理back事件,就要重写popupWindow布局文件的onKeyListener()事件,这样才能自己做处理。比如下面的几行代码:

.setOnKeyListener(new OnKeyListener()
{// 手机键盘上的返回键
public boolean onKey(View v, int keyCode, KeyEvent event)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_BACK:
if (softkeyboard_popupWindow != null && softkeyboard_popupWindow.isShowing())
{
softkeyboard_popupWindow.dismiss();
}
break;
}

}


一个朋友这样想的办法:(问题是setFocusable(false),这样后,里面的布局控件不能获得焦点,如果有一个EditText,就不能输入内容了,肯定是不行的。我想了想,可以设置setOutsideTouchable(true);,让popupWindow以外的布局可以获得触摸事件,然后我们重写onTouchEvent,去让popupWindow消失,如下面写的一样。

又测试了一下,终于明白了,.setFocusable(false),之所以要设置为false,就是为了让popupWindow出现的时候,它所依赖的父亲view仍然能获取到焦点,这样重写onTouchEvent就可以起作用了,如果设置为true,当你的popupWindow出现的时候,它的父亲view是获取不到焦点的,所以你重写onTouchEvent也没用,根本截获不到这个事件。

代码如下popupWindow.setFocusable(false);//focusable要为false(不设置默认的就是False);
//这是Activity 的OnTouchEvent。OnTouchEvent代表的是Activity 获得事件(即为PopupWindow之外)

@Override

public boolean onTouchEvent(MotionEvent event) {

// TODO Auto-generated method stub

if (popupWindow != null && popupWindow.isShowing()) {

popupWindow.dismiss();

popupWindow = null;

}

return super.onTouchEvent(event);

}


还有一个朋友记录了一些他的学习内容。如下:

由于系统自带的Menu不好看 而且不能自己改样式

所以很多应用都用Popupwindow自定义了

最精典的莫过于UC和天天的Menu鸟

网上有模仿UCweb的自定义menu的源码,下面是三个比较经典的文章:

  1. Android提高十八篇之自定义Menu(TabMenu)
  2. 【源码发布】仿UCWEB7.4界面最新Menu菜单 源码放出~!
  3. 模仿UCweb菜单

这三个都是使用PopupWindow来做的,然后往PopupWindow增加一个子View,子View的布局就是menu的布局。

出现和退出的动画:可以给PopUpWindow或它的子view。这些问题可以看看上面三个例子的源码。

网上所有用PopupWindow做的menu有个共同特点:就是点击menu键出现PopupWindow,然后再点击menu键无法使 PopupWindow退出/dismiss()。甚至有的会多此一举,点击一个按钮显示menu,同时还在按钮点击事件写了这时候点击按钮,menu会 退出的代码。

为什么说多此一举呢?因为当给PopupWindow设置了setFocusable(true),menu显示后,点击menu其他任何地 方,menu都会消失,也就是说这时候按钮的点击事件其实是不响应的。同时只响应键盘的返回键,其他按键均不响应,比如点击menu键,没有任何反应。

要解决这个问题很简单,就是给PopupWindow的子View设置下面的代码:

menuView.findViewById(R.id.layout).setOnKeyListener(

new OnKeyListener() {

public boolean onKey(View v, int keyCode, KeyEvent event) {

// TODO Auto-generated method stub

Log.w("qqqqqq", "onKey");

if (keyCode == KeyEvent.KEYCODE_MENU) {

showPopup();

}

return false;

}

});


记住,一定要给PopupWindow设置setFocusable(true),要不然点击menu其他地方以及返回键,menu都不会退出。且这时候是响应PopupWindow的parent的menu事件的。

下面阐述为什么这么写之后,当PopupWindow显示后,点击menu键PopupWindow会退出的原因:

首先得明白为什么给PopupWindow setFocusable(true)后,点击menu出现PopupWindow后再点击menu没反应的原因。PopupWindow初始化的时候一 般都指定了在哪个View上出现,我们称这个View为parent。parent里面写了点击menu出现PopupWindow的事件,如果给 PopupWindow setFocusable(true),此时屏幕的焦点在PopupWindow上面,肯定是不会响应parent的按键事件的,它只会响应 PopupWindow的按键事件。

但是PopupWindow的本质是Window,没有继承View类,自己没有onkeyDown或onkey或dispatchKey这些事件的。我刚开始试着实现这些接口,但是按键依然不响应,不知原因。因现在对按键的原理还不熟,无法阐述其原因。

然后我想绕道而行,就是给PopupWindow的子View注册按键事件,setKeyListener,刚开始我在子View的xml设置了 android:focusable=”true” 但按键事件依然不响应。。。。纠结啊纠结。。。然后没得办法,我google了所有关于PopupWindow的文章。。。最后终于被我发现。。。需要给 PopupWindow的子View 设置setFocusableInTouchMode(true)。这时候按键事件就响应了。。。

最后加红的这段代码可困扰我好几天啊,就一个属性 我是翻来覆去整了好几天啊

赶紧记录一下



最终的办法:

其实这里还是有办法的,一行代码就可以,网上很多朋友说这个是PopupWindow的一个bug.

popupWindow.setBackgroundDrawable(null);//new BitmapDrawable());

文档上写可以设置一个背景图或者设为null,但是设置为null是不行的,感兴趣的朋友可以试试。

popupWindow.setBackgroundDrawable(new BitmapDrawable());这样设置一下就可以实现标题说的了,点击popupWindow以外的区域就可以让它消失了。其实我看了BitmapDrawable这个类,这个类的无参构造函数已经标为@deprecated了,就是说已经不建议使用了。我们这里这么用也是投机取巧了。

 如果你想让它消失的时候做一些事情,就可以重写setOnDismissListener(PopupWindow.OnDismissListener onDismissListener)这个方法,去写个回调函数,去做你想做的操作。


还有一个发现:我们设置popupWindow的布局文件如下:这样可以相应back事件,这样就是说在popupWindow获取焦点的时候,拦截

它的back事件,然后让popupWindow消失。其实,这个时候,popupWindow里面布局的任何一个控件,比如Button,都可以拦截onKeyListener事件了

当然你可以设置popupWindow里面布局每个子控件的属性,然后在事件里做一些你想做的操作,比如:

button.setFocusableInTouchMode(true);

button.setOnKeyListener(new View.OnKeyListener() {   });


contentView.setFocusableInTouchMode(true);
contentView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.i("tag", "XXX0");
if (keyCode == KeyEvent.KEYCODE_BACK) {
popupWindow.dismiss();
}
return false;
 
}
});


又发现朋友给了这个方法:

你把除popwindow意外的区域 用一个linear圈起来。。。然后这个linear设置ontouch监听。。event.getAction()==MotionEvent.ACTION_UP 时 ,popwindow.dismiss();

没试过,不过感觉应该没问题,不过就是换种思想吧。这个方法也不错的。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值