点击外部消失,只需要设置popupWindow.setBackgroundDrawable(new PaintDrawable());

设置

popupWindow.setFocusable(true);
//popupWindow.setBackgroundDrawable(new PaintDrawable());
popupWindow.setOutsideTouchable(true);
popupWindow_view.setFocusableInTouchMode(true);也可以是点击外部消失

响应back键消失比较简单,在popview加上setOnKeyListener事件,判断按键是不是back就可以了

但是再加上响应menu键就麻烦了。点击menu键出现popwindows跟出现后点击menu先响应的位置分别是不一样,总是出现焦点冲突。下面是一个比较好的解决办法

一下内容转自http://blog.csdn.net/admin_/article/details/7278402

使用PopupWindow来做自定义menu,往PopupWindow增加一个子View,子View的布局就是menu的布局。

出现和退出的动画:可以给PopUpWindow或它的子view添加。

网上所有用PopupWindow做的menu有个共同特点:就是点击menu键出现PopupWindow,然后再点击menu键无法使PopupWindow退出/dismiss()。

当给PopupWindow设置了setFocusable(true),menu显示后,点击menu其他任何地方,menu都会消失,但是这时候按钮的点击事件其实是不响应的。同时只响应键盘的返回键,其他按键均不响应,比如点击menu键,没有任何反应。

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

        //sub_view 是PopupWindow的子View
sub_view.setFocusableInTouchMode(true);
sub_view.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if ((keyCode == KeyEvent.KEYCODE_MENU)&&(mPopupWindow.isShowing())) {
mPopupWindow.dismiss();// 这里写明模拟menu的PopupWindow退出就行
return true;
}
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)。这时候按键事件就响应了。。。

下面附上完整代码:

    /*必须重写,否则点击MENU无反应  为了让他不显示,下面onMenuOpened()必须返回false*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add("menu");// 必须创建一项
return super.onCreateOptionsMenu(menu);
}
/**
* 拦截MENU
*/
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
if(mPopupWindow != null){
if(!mPopupWindow.isShowing()){
/*最重要的一步:弹出显示 在指定的位置(parent) 最后两个参数 是相对于 x / y 轴的坐标*/
mPopupWindow.showAtLocation(findViewById(R.id.linear_menu_parent), Gravity.BOTTOM, 0, 0);
}
}
return false;// 返回为true 则显示系统menu
} private void initPopuWindow(int menuViewID){
LayoutInflater mLayoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
/*设置显示menu布局 view子VIEW*/
sub_view = mLayoutInflater.inflate(menuViewID, null);
/*第一个参数弹出显示view 后两个是窗口大小*/
mPopupWindow = new PopupWindow(sub_view, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
/*设置背景显示*/
mPopupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.bg_menu_popup));
/*设置触摸外面时消失*/
mPopupWindow.setOutsideTouchable(true);
/*设置系统动画*/
mPopupWindow.setAnimationStyle(android.R.style.Animation_Dialog);
mPopupWindow.update();
mPopupWindow.setTouchable(true);
/*设置点击menu以外其他地方以及返回键退出*/
mPopupWindow.setFocusable(true); /** 1.解决再次点击MENU键无反应问题
* 2.sub_view是PopupWindow的子View
*/
sub_view.setFocusableInTouchMode(true);
sub_view.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if ((keyCode == KeyEvent.KEYCODE_MENU)&&(mPopupWindow.isShowing())) {
mPopupWindow.dismiss();// 这里写明模拟menu的PopupWindow退出就行
return true;
}
return false;
}
}); /*监听MENU事件*/
menu = new View[3];
menu[0] = sub_view.findViewById(R.id.menu_0);
menu[1] = sub_view.findViewById(R.id.menu_1);
menu[2] = sub_view.findViewById(R.id.menu_2); menu[0].setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// doSomething }
}); menu[1].setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// doSomething }
}); menu[2].setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// doSomething }
});
}

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

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

Android 响应menu,back键,点击外部消失的更多相关文章

  1. PopupWindow 点击外部和返回键无法消失背后的真相(setBackgroundDrawable(Drawable background))

    刚接手PopupWindow的时候,我们都可能觉得很简单,因为它确实很简单,不过运气不好的可能就会踩到一个坑: 点击PopupWindow最外层布局以及点击返回键PopupWindow不会消失 新手在 ...

  2. android学习之4种点击事件的响应方式

    如题,下面就一一列出对点击事件响应的4种方式: 第一种:内部类的形式: package com.example.dail; import android.net.Uri; import android ...

  3. Android开发中EditText的点击Enter键焦点改变处理(获取焦点和失去焦点交互变化)

    最近因为项目需要,需要将EditText的焦点转移到LineraLayout上: 即为EditText输入完毕后,点击回车键或者按压其他嵌入式android设备的OK键,获取LineraLayout的 ...

  4. Android 设置软键盘搜索键以及监听搜索键点击事件

    如图所示,有时候为了布局美观,在搜索时没有搜索按钮,而是调用软件盘上的按钮.调用的实现只需要在XML在输入框中加入android:imeOptions="actionSearch" ...

  5. Android实例1:button点击响应

    个人网站http://www.ravedonut.com/ Layout xml文件 <RelativeLayout android:layout_width="wrap_conten ...

  6. Android 监听返回键退出程序的两种实现

    1.Android 双击返回键退出程序 思路:用户按下返回键时设定一个定时器来监控是否2秒内实现了退出,如果用户没有接着按返回键,则清除第一次按返回键的效果,使程序还原到第一次按下返回键之前的状态.定 ...

  7. Android监听返回键、Home键+再按一次返回键退出应用

    Android监听返回键需重写onKeyDown()方法 Home键keyCode==KeyEvent.KEYCODE_HOME @Override public boolean onKeyDown( ...

  8. Android菜鸟成长记4-button点击事件

    Button 1.button按钮的创建 一般来说,在我们新建一个Android项目的时候,会有会默认有一个activity_main.xml的文件 如果你在新建项目的时候,把Create Activ ...

  9. Android按钮的四种点击事件

    本文记录一下按钮的四种点击事件 第一种 public class MainActivity extends Activity { @Override protected void onCreate(B ...

随机推荐

  1. Liunx 重定向,管道符(转)

    原作网址:http://blog.csdn.net/qq_16811963/article/details/52997178 输出重定向 >代表以覆盖的方式将命令的正确输出输出到指定的文件或设备 ...

  2. 基于spring boot的统一异常处理

    一.springboot的默认异常处理 Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容. 例如这里我 ...

  3. [转]安装 Silverlight 5/silverlight4 出错的解决方法

    安装Silverlight 5时,如果 如图: 安装Silverlight 5时,如果你的VS不是英文版,那么可能会出现以下错误: Visual Studio 2010 SP1 that matche ...

  4. gerrit管理下的git代码提交小技巧

    1.提交代码git checkout targetbranch 切换至目标分支git pull origin targetbranch 拉取目标分支最新内容git add 修改文件git commit ...

  5. 201621123008 《Java程序设计》第八周学习总结

    1. 本周学习总结 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 源代码: public boolean contains(Object o ...

  6. python基础之Day5

    一.基本概念 为什么要有数据: 计算机能够像人一样识别现实生活中的状态是因为计算机事先将数据存到了记忆中 为什么要分类型: 满足现实世界不同状态的需要 二.数据类型(研究定义,作用,常见操作) 1.整 ...

  7. Linux 双网关(电信与联通)

    经常有这种需求,一台Linux服务器配置电信IP和网通IP,默认情况下,后启动的网卡的网关生效.南电信北网通,配置电信和网通IP,无非是为了减少网络延时,使电信用户的请求响应在电信网络中传输,网通用户 ...

  8. Linux renew ip command

    $ sudo dhclient -r    //release ip 释放IP$ sudo dhclient       //获取IP Now obtain fresh IP:$ sudo dhcli ...

  9. [SoapUI] 判断工程下某个文件是否存在,存在就删除

    def excelName = "AllTests-Fails" String projectPath = context.expand( '${projectDir}' ) St ...

  10. PropertyPlaceholderConfigurer

    PropertyPlaceholderConfigurer Spirng在生命周期里关于Bean的处理大概可以分为下面几步: 加载 Bean 定义(从xml或者从@Import等) 处理 BeanFa ...