zoukankan      html  css  js  c++  java
  • Android实战技巧: ListView之ContextMenu无法弹出

    问题

    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.

  • 相关阅读:
    LGPrep的一点小问题
    百度地图API的事件处理:覆盖物阻止冒泡
    HTML5截取视频第一帧作为预览图片
    20165105 第二周学习总结
    20165105课下作业
    20165105第一周学习查缺补漏
    第四周课下作业20165105
    20165105 201620172 《Java程序设计》第1周学习总结
    我期望的师生关系
    .NET使用NPOI组件将数据导出Excel
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3148116.html
Copyright © 2011-2022 走看看