Focus事件处理
2016-05-09 11:34
225 查看
首先我们来看一下View是怎么获得Focus的.Focus是如何在View间跳转的呢?
查阅源码可以看到对KeyEvent的处理是在ViewRootImpl.processKeyEvent()
mView.dispatchKeyEvent(event)对事件进行了分发,并且如果返回true将结束事件处理,返回FINISH_HANDLED.
我们知道view对事件的处理都是从dispatchKeyEvent分发开始的,看一下dispatchKeyEvent的源码是怎样的呢?
如果View设置了OnKeyListener,
并且View是ENABLED的,满足前面两个条件后,就会进行第三个条件判断,即回调onKey方法对事件进行处理。这里就会有个疑问了,如果onKey也返回true,那dispatchKeyEvent就直接返回ture,
整个事件处理是不是就结束了?
这里可以进行一下测试:
对一个view设置OnKeyListener,并在onKey方法里,如果是KEYCODE_DPAD_DOWN,直接返回true.
可以看到,当Focus在TextView,点击KEYCODE_DPAD_UP,Focus可以跳到Button,但是点击KEYCODE_DPAD_DOWN
Focus就不会跳到BUTTON2.(如果在onKey里返回true,onClick事件也不会触发。这里可以认为是事件已经被消化,不会再往下分发,)
回到我们的focus问题上,如果dispatchKeyEvent返回true,focus不会跳转,说明focus的处理还在dispatchKeyEvent之后,这里回到ViewRootImpl.processKeyEvent()里。
这里根据KEYCODE设定view的focus方向。
使用上面Focus从TextView到BUTTON的例子,这里mView就是TextView,这时候TextView是有focus的,所以这里的focused也是TextView。focused.focusSearch(direction)就是通过已经获取了focus的view和下一次focus的方向找到下一次要focus的view。说得好绕,还是直接看代码吧ViewRootImpl.focusSearch()。
真正处理的方法在FocusFinder.findNextFocus(),
这里要注意mView是TextView的parent,focused是Text
4000
View.
findNextUserSpecifiedFocus先找用户自定义的下一个focusview,这里我们没有定义,不需要考虑。
root.addFocusables将所有可以获取focus的view添加到focusables里面
ViewGroup.addFocusables()
像遍历树一样遍历root的所有子view和孙view,然后调用View.addFocusable把isFocusable的view添加到focusables.
把所有focusable的view找出来后,就可以通过算法找到下一个要focus的view了。
next = findNextFocus(root, focused,focusedRect, direction, focusables);(看不懂算法是如何实现1))
现在来看一下第二个问题:ViewGroup和子类View哪一个获取focus.
在ViewGroup有个属性android:descendantFocusability
属性的值有3种:
"beforeDescendants": ViewGroup会优先其子类控件而获取到焦点
– ViewGroup获得focus(ViewGroup获得focus后,在按其他键,focus也跳不到去子类)
"afterDescendants":只有当其子类不需要获取焦点时ViewGroup才获取焦点–
子类先获得focus(如果所有子类focusable = false,
父类获取focus)
"blocksDescendants":ViewGroup覆盖子类直接获取焦点 --ViewGroup获得focus
这个是怎么实现的呢?其实就在ViewGroup.addFocusables
FOCUS_BLOCK_DESCENDANTS:
只加自己到focusable,不加孩子
FOCUS_AFTER_DESCENDANTS:
只加孩子不加自己到focusable
FOCUS_BEFORE_DESCENDANTS:
先加孩子,再加自己到focusable
3. focusableInTouchMode触摸的时候会获取focus
查阅源码可以看到对KeyEvent的处理是在ViewRootImpl.processKeyEvent()
mView.dispatchKeyEvent(event)对事件进行了分发,并且如果返回true将结束事件处理,返回FINISH_HANDLED.
我们知道view对事件的处理都是从dispatchKeyEvent分发开始的,看一下dispatchKeyEvent的源码是怎样的呢?
如果View设置了OnKeyListener,
并且View是ENABLED的,满足前面两个条件后,就会进行第三个条件判断,即回调onKey方法对事件进行处理。这里就会有个疑问了,如果onKey也返回true,那dispatchKeyEvent就直接返回ture,
整个事件处理是不是就结束了?
这里可以进行一下测试:
对一个view设置OnKeyListener,并在onKey方法里,如果是KEYCODE_DPAD_DOWN,直接返回true.
可以看到,当Focus在TextView,点击KEYCODE_DPAD_UP,Focus可以跳到Button,但是点击KEYCODE_DPAD_DOWN
Focus就不会跳到BUTTON2.(如果在onKey里返回true,onClick事件也不会触发。这里可以认为是事件已经被消化,不会再往下分发,)
回到我们的focus问题上,如果dispatchKeyEvent返回true,focus不会跳转,说明focus的处理还在dispatchKeyEvent之后,这里回到ViewRootImpl.processKeyEvent()里。
这里根据KEYCODE设定view的focus方向。
使用上面Focus从TextView到BUTTON的例子,这里mView就是TextView,这时候TextView是有focus的,所以这里的focused也是TextView。focused.focusSearch(direction)就是通过已经获取了focus的view和下一次focus的方向找到下一次要focus的view。说得好绕,还是直接看代码吧ViewRootImpl.focusSearch()。
真正处理的方法在FocusFinder.findNextFocus(),
这里要注意mView是TextView的parent,focused是Text
4000
View.
findNextUserSpecifiedFocus先找用户自定义的下一个focusview,这里我们没有定义,不需要考虑。
root.addFocusables将所有可以获取focus的view添加到focusables里面
ViewGroup.addFocusables()
像遍历树一样遍历root的所有子view和孙view,然后调用View.addFocusable把isFocusable的view添加到focusables.
把所有focusable的view找出来后,就可以通过算法找到下一个要focus的view了。
next = findNextFocus(root, focused,focusedRect, direction, focusables);(看不懂算法是如何实现1))
现在来看一下第二个问题:ViewGroup和子类View哪一个获取focus.
在ViewGroup有个属性android:descendantFocusability
属性的值有3种:
"beforeDescendants": ViewGroup会优先其子类控件而获取到焦点
– ViewGroup获得focus(ViewGroup获得focus后,在按其他键,focus也跳不到去子类)
"afterDescendants":只有当其子类不需要获取焦点时ViewGroup才获取焦点–
子类先获得focus(如果所有子类focusable = false,
父类获取focus)
"blocksDescendants":ViewGroup覆盖子类直接获取焦点 --ViewGroup获得focus
这个是怎么实现的呢?其实就在ViewGroup.addFocusables
FOCUS_BLOCK_DESCENDANTS:
只加自己到focusable,不加孩子
FOCUS_AFTER_DESCENDANTS:
只加孩子不加自己到focusable
FOCUS_BEFORE_DESCENDANTS:
先加孩子,再加自己到focusable
3. focusableInTouchMode触摸的时候会获取focus
相关文章推荐
- JS实现密码框根据焦点的获取与失去控制文字的消失与显示效果
- JavaScript实现文本框中默认显示背景图片在获得焦点后消失的方法
- 使用jquery给input和textarea设定ie中的focus
- Jquery实现兼容各大浏览器的Enter回车切换输入焦点的方法
- 文本框倒叙输入让输入框的焦点始终在最开始的位置
- JavaScript判断表单为空及获取焦点的方法
- jQuery实现dialog设置focus焦点的方法
- JavaScript事件类型中焦点、鼠标和滚轮事件详解
- JavaScript实现为input与textarea自定义hover,focus效果的方法
- JS实现方向键切换输入框焦点的方法
- JavaScript使用focus()设置焦点失败的解决方法
- 当某个文本框成为焦点时即清除文本框内容
- input 输入框获得/失去焦点时隐藏/显示文字(jquery版)
- JavaScript 关于元素获取焦点(隐藏元素与div)
- 有效的捕获JavaScript焦点的方法小结
- textarea焦点的用法实现获取焦点清空失去焦点提示效果
- 当jQuery1.7遇上focus方法的问题
- 在Form_Load里面调用Focus无效的解决方法
- javascript实现焦点滚动图效果 具体方法
- 焦点透视与成角透视