您的位置:首页 > 移动开发 > Android开发

android listview焦点争端

2016-05-13 00:26 537 查看
listview没有响应事件,归根结底是因为listview的item条目中有Button 、ImageView、EditView等获取优先获取焦点的的子组件。,由于这样的子组件有更高的优先级获取焦点,所以传递过来的事件被消费了,而不再响应listview的触目事件。要想解决这个问题,必须分析出现这问题的原因。

在分析这个问题实现说明涉及到的三个方法dispatchTouchEvent(MotionEvent ev)【事件分发】、onInterceptTouchEvent(MotionEvent ev)【事件拦截】、onTouchEvent(MotionEvent
ev)【事件响应】。当然,能够响应这三个方法的控件包括:ViewGroup及其子类、Activity

ViewGroup能够响应三个方法,Activity不能够响应时间的拦截。还有如果view有子组件时,就可以响应三个方法,如果没有子控件的话,就只有事件响应的方法。

TouchEvent事件发生时,会从Activity的dispatchTouchEvent(MotionEvent ev)方法以隧道的方式【从根节点依次向下传递事件,直到最内层元素后者在中间某一元素停止传递】将事件传递给最外层View的dispatchTouchEvent(MotionEvent ev)方法进行分发。

dispatchTouchEvent(MotionEvent ev)的处理事件模型:

如果返回值为true,则由当前view的onTouchEvent(MotionEvent ev)消费事件,同时不再向下传递事件,以后所有的事件都会先传递到该view组件

如果返回值为false,假如事件直接来自Activity,则返回给Activity的onTouchEvent(MotionEvent ev)消费事件;否则返回给父的onTouchEvent(MotionEvent ev)消费事件

如果调用系统默认的super.dispatchTouchEvent(MotionEvent ev),事件会自动分发给当前的view的onInterceptTouchEvent(MotionEvent ev)方法

onInterceptTouchEvent(MotionEvent ev)的处理事件模型:

在外层的View的dispatchTouchEvent(MotionEvent ev)返回系统默认的super.dispatchTouchEvent(MotionEvent ev)情况下,事件会分发给当前的onInterceptTouchEvent(MotionEvent ev)的处理事件,判断是否·拦截事件。假如拦截事件事件传递到当前的onTouchEvent(MotionEvent ev)处理;否则,事件放行,将事件传递给子view的dispatchTouchEvent(MotionEvent ev)进行分发事件。当调用系统默认的super.onInterceptTouchEvent(MotionEvent
ev),默认事件被拦截

onTouchEvent(MotionEvent ev)的处理事件模型:

在dispatchTouchEvent(MotionEvent ev)返回super.dispatchTouchEvent(MotionEvent ev)和onInterceptTouchEvent(MotionEvent ev)返回true或者super.dispatchTouchEvent(MotionEvent ev)的时候,会被调用该事件。

如果当前返回false,则返回事件向上传递,有父类的onTouchEvent(MotionEvent ev)处理消费,父类也返回false就继续向上传递事件,直到顶层是件消失,而且也接收不到下一次事件

如果返回了true,则接受并消费事件

如果返回super.onTouchEvent(MotionEvent ev)则默认返回false,处理机制和上面返回false一样。

还有就是组件获取焦点的优先级:可以设置属性descendantFocusability,在item条目布局的根节点设置该属性

接受三个属性值:

beforeDescendants:viewgroup会优先其子类控件而获取到焦点

afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

当然也可以设置子控件的Android:focusable="false"

聚焦分析:

当用户通过键盘(或者轨迹球)操作的时候,有必要聚焦当前接受输入的UI元素,但是有时候就不需要。比如触摸屏事件,点击某个UI元素也不会导致该元素聚焦,此时【高亮效果】由Pressed状态来标识,不会进入聚焦状态,即使调用requestFocus也不行的。

区分这两种情况需要TouchMode模式来标识。如果触摸事件,则进入该模式;否则调用View的isINTouchMode判断是否处于该模式下。

例外情况是,想EditView、Button这样的组件也会在触摸模式下获取焦点,这样会导致listview的事件无响应,先获取事件。可以调用在TouchMode模式也能获取焦点setFocusableInTouchMode(true),调用isFocusableInTouchMode是够可以获取焦点。

截断listview的item条目中优先获取焦点的方法为:

item条目的根目录下设置:
android:focusable="true"  【非触摸的属性】
android:focusableInTouchMode="true"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: