问题

Activity中使用了ListView作为布局.当每一列表项中含有默认能获取焦点的子View时有可能会对ListView的某些事件有影响:

1. OnItemClick

2. OnItemLongClick

3. ContextMenu

这三个事件都无法正确响应.

对于ContextMenu.首先要在onCreate中注册Activity的ContextMenu到ListView上:

registerForContextMenu(mListView);

要在onDestroy中取消注册:

unregisterForContextMenu(mListView);

一个简单的解法就是在Adapter中构建列表中的每个Item时,把相应事件Click或者LongClick加到具体的item上面.但这样的话,会造成逻辑十分混乱.而且点击Item或者长按Item时不会有Focus的Selection.此现象十分奇怪,必定另有隐情!

Google了一下,果然StackOverflow上面有很多关于ListView 的ContextMenu的问题,首先要注意的是基本的用法,也就是上面提到的要registerForContextMenu.之后就是奇怪事件发生的地方了:

如果ListView的列表项中含有默认就有Focus的子View(如Checkbox)时,就无法获取ContextMenu.

这时就需要把Checkbox的Focus属性改变:

android:focusable="false"

然后就可以了.

其实,ContextMenu也就是长按事件来的.所以不光是ContextMenu出不来,连onItemClick, onItemLongClick也都出不来!如果把Item中的Checkbox的android:focusable属性设置成false,就可以解决这些问题.

但是,没有人能解释清楚为啥会酱紫!

看了ListView的源代码,ListView并没有控制Click和LongClick以及ContextMenu(ContextMenu也是由长按事件触发的).这些事件是由它的父类AbsListView来管理的.
在AbsListView中有一个用于检查LongClick的Runnable,它里面有这样一个判断:

View v  = getChildAt(position);
if (v != null && !v.hasFocusable()) {
.... do long click handling which will trigger context menu.
}

也就是说每当长按一个项时,会检查其hasFocusable()返回值,返回false时才做长按的动作.其他地方比如onTouchEvent时也都会如此的检查,发现hasFocusable()为true时就直接返回!这里注意,检查的是所点击的列表项,所以如果列表项的布局不一样,现象就有可能不一样!
那么View.hasFocusable(),当View的focusable为true时返回true,或者当其有子View的focusable为true时,就返回true.简单讲就是View本身focusable为true或者有子View的focusable为true时就返回true.
因为,ListItem里面有CheckBox,它的focusable属性默认就是true的.所以就不会有ContextMenu弹出来.如果把CheckBox的focusable属性设置为false,就可以正常的弹出了.
可以还是没弄明白为啥要酱紫设计?需要牛人来指点下!

扩展

目前来看默认就有focusable属性的有Button, CompoundButton, SeekBar, EditText,ImageButton,AutoCompleteTextView,WebView,WebTextView和它们的子类(怎么找出来了呢,到系统的style文件frameworks/base/core/res/res/value/styles.xml里面搜索focusable属性为true).所以理论上来讲,如果把这些Widget放入ListView里面时,ListView的OnItemClick,OnItemLongClick以及ContextMenu都不会有效果.解决办法就是把它们的focusable属性设为false.

Android实战技巧: ListView之ContextMenu无法弹出的更多相关文章

  1. Android实战技巧:深入解析AsyncTask

    AsyncTask的介绍及基本使用方法 关于AsyncTask的介绍和基本使用方法可以参考官方文档和Android实战技巧:多线程AsyncTask这里就不重复. AsyncTask引发的一个问题 上 ...

  2. Android ListView 长按列表弹出菜单

    Android ListView 长按列表弹出菜单 设置长按菜单 listView.setOnCreateContextMenuListener(new View.OnCreateContextMen ...

  3. iOS开发实用技巧—在手机浏览器头部弹出app应用下载提示

    iOS开发实用技巧—在手机浏览器头部弹出app应用下载提示 本文介绍其简单使用: 第一步:在本地建立一个访问的服务端.  打开本地终端,在本地新建一个文件夹,在该文件夹中存放测试的html页面.   ...

  4. Android 应用监听自身卸载,弹出用户反馈调查

    监听卸载情景和原理分析 1,情景分析 在上上篇博客中我写了一下NDK开发实践项目,使用开源的LAME库转码MP3,作为前面几篇基础博客的加深理解使用的,但是这样的项目用处不大,除了练练NDK功底.这篇 ...

  5. Android初级教程以动画的形式弹出窗体

    这一篇集合动画知识和弹出窗体知识,综合起来以动画的形式弹出窗体. 动画的知识前几篇已经做过详细的介绍,可翻阅前面写的有关动画博文.先简单介绍一下弹出窗体效果的方法: 首先,需要窗体的实例:PopupW ...

  6. 【Unity技巧】自定义消息框(弹出框)

    写在前面 这一篇我个人认为还是很常用的,一开始也是实习的时候学到的,所以我觉得实习真的是一个快速学习工程技巧的途径. 提醒:这篇教程比较复杂,如果你不熟悉NGUI.iTween.C#的回调函数机制,那 ...

  7. WPF 如何控制右键菜单ContextMenu的弹出

    在具体做一些项目的时候,有时候需要需要先左键点击某个节点,然后再右键点击节点的时候才弹出右键菜单,所以直接右键点击时需要禁用掉右键菜单,这里比如我们为Grid添加了ContextMenu,但是我们需要 ...

  8. Android封装类似微信的顶部TitleBar弹出的PopupWindow代码

    Android仿微信顶部titlebar,点击加号弹出的PopupWindow,是封装好的PopupWindow,直接拿来用即可,先看效果图:  调用代码非常简单,这是MainActivity的代码: ...

  9. Android的Toolbar(含溢出菜单设置[弹出菜单的使用])的使用PopMenu的样式

    http://blog.csdn.net/yingtian648/article/details/52432438(转载) 1.在Toolbar.xml中设置弹出菜单的风格(app:popupThem ...

随机推荐

  1. C语言拾遗--static

    C程序一直由下列部分组成: 正文段——CPU执行的机器指令部分:一个程序只有一个副本:只读,防止程序由于意外事故而修改自身指令: 初始化数据段(数据段)——在程序中所有赋了初值的全局变量,存放在这里. ...

  2. 【Java Web】使用URLRewrite实现网站伪静态

    大部分搜索引擎都会优先考虑收录静态的HTML页面,而不是动态的*.jsp.*.php页面.但实际上绝大部分网站都是动态的,不可能全部是静态的HTML页面,因此互联网上大部分网站都会考虑伪静态——就是将 ...

  3. 百度地图api基本用法

    首先 ,如果想调用百度地图api,你需要获取一个百度地图api的密钥. 申请密钥很简单,在百度地图api的首页就有相关链接,填写相关信息百度就会给你一个密钥了. 接下来,就是引入百度地图的api 关键 ...

  4. C#多线程的死锁演示

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  5. python对web服务器做压力测试并做出图形直观显示

    压力测试有很多工具啊.apache的,还有jmeter, 还有loadrunner,都比较常用. 其实你自己用python写的,也足够用. 压力测试过程中要统计时间. 比如每秒的并发数,每秒的最大响应 ...

  6. CloudStack 4.2 新功能:集成SNMP进行系统监控(原理篇)

    作者微博:http://weibo.com/tianchunfeng CloudStack 4.2 版本发布在即,相信不久后对 4.2 版本新功能(共有13个)的介绍会逐渐多起来.因为无论是从架构底层 ...

  7. VB.net数据库编程(03):一个SQLserver连接查询的简单样例

    这个样例,因为在ADO.net入门已经专门学了,再次进行复习 一下. 主要掌握连接字串的情况. 过程就是: 1.引用System.Data.SqlClient.而Access中引用 的是System. ...

  8. MYSQL查询表结构

    mysql查看表结构命令,如下: desc 表名;show columns from 表名;describe 表名;show create table 表名; use information_sche ...

  9. 页面爬虫(获取其他页面HTML)加载到自己页面

    //前台 <div id="showIframe"></div> $(document).ready(function() { var url = &quo ...

  10. Linux内核驱动将多个C文件编译成一个ko文件的方法——每一个C文件中都有module_init与module_exit

    以两个C文件为例: 将本该被分别编译成adc_device.ko和adc_driver.ko的adc_device.c.adc_driver.c编译成一个ko文件! 採用方法: 第一步.改动C文件 1 ...