在 android 中。焦点的获取和事件几乎相同,有一个分发机制。一般来说View 树上上层节点的 ViewGroup 比底层节点的 View 有更高的优先级获取焦点。这体如今 ViewGroup 有一个属性 descendantFocusability 可以用来控制焦点获取的优先级。 该属性的值有三种:

  • beforeDescendants:ViewGroup 会优先其子类控件而获取到焦点,假设父控件不获取焦点,子控件才可能会获得焦点
  • afterDescendants:仅仅有当其子类控件不须要获取焦点时。ViewGroup 才可能获取焦点
  • blocksDescendants:viewgroup 会堵塞子类控件获得焦点。不管 ViewGroup 是否获取焦点,子控件都不可以获得焦点

怎样推断 View 是否可以获取焦点

由于上面的原因。推断一个 View 是否有可能获得焦点。就与它全部的父节点有关系了,所以 View 的 hasFocusable 方法实现例如以下:

public boolean hasFocusable() {
if (!isFocusableInTouchMode()) {
for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
final ViewGroup g = (ViewGroup) p;
if (g.shouldBlockFocusForTouchscreen()) {
return false;
}
}
}
return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
}
  1. 在触摸模式下假设不可获取焦点。先遍历 View 的全部父节点,假设有一个父节点设置了堵塞子 View 获取焦点,那么该 View 就不可能获取焦点
  2. 在触摸模式下假设不可获取焦点,而且没有父节点设置堵塞子 View 获取焦点。和在触摸模式下假设可以获取焦点,那么才推断 View 自身的 visiable 和 focusable 属性,来决定是否可以获取焦点。不可见的 View 当然也不能获取焦点,所以仅仅有 visiable 和 focusable 同一时候为 true,该View 才可能获取焦点

怎样推断 ViewGroup 是否可以获取焦点

推断一个 ViewGroup 是否可能获取到焦点,也与它的子 View 有关系了。假设子 View 可以获取焦点,辣么。就行算作这个 ViewGroup 也可能获取(消耗)焦点,所以 ViewGroup 的 hasFocusable 方法实现例如以下:

public boolean hasFocusable() {
if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
return false;
} if (isFocusable()) {
return true;
} final int descendantFocusability = getDescendantFocusability();
if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
final int count = mChildrenCount;
final View[] children = mChildren; for (int i = 0; i < count; i++) {
final View child = children[i];
if (child.hasFocusable()) {
return true;
}
}
} return false;
}

依据上面的源代码可知,推断 ViewGroup 是否可以获取焦点就简单多了

  1. 假设 ViewGroup visiable 和 focusable 都为 true,就算可以获取焦点
  2. 假设不满足第 1 点,假设子 View 节点可以获取焦点,该 ViewGroup 也算能获取焦点(通过递归实现)
  3. 否则。就算作不可以获取到焦点
  4. ViewGroup 自己可以获取焦点,全然没有考虑是否在触摸模式的情况。不晓得是不是 google project师的 bug,快到 google groups 提问 ^-^!

View 是否可以获取焦点的实际应用

View 是否可以获取焦点。通常在 AbsListView 的 OnItemClickListener,EditText,Button 的使用和 key 事件分发中会应用到。

比方 ListView 的 OnItemClickListener,仅仅有在 ListView 的 ItemView 不能获取到 focus 的情况下。才会调用 OnItemClickListener 的 onItemClick 方法。详细代码可以參考 AbsListView 的 onTouchUp 方法:

private void onTouchUp(MotionEvent ev) {
switch (mTouchMode) {
case TOUCH_MODE_DOWN:
case TOUCH_MODE_TAP:
case TOUCH_MODE_DONE_WAITING:
......
该省就省。我是省略代码切割符 ^_^
......
if (inList && !child.hasFocusable()) {
if (mPerformClick == null) {
mPerformClick = new PerformClick();
} final AbsListView.PerformClick performClick = mPerformClick;
performClick.mClickMotionPosition = motionPosition;
performClick.rememberWindowAttachCount(); ......
该省就省,我是省略代码切割符 ^_^
......
mTouchModeReset = new Runnable() {
@Override
public void run() {
mTouchModeReset = null;
mTouchMode = TOUCH_MODE_REST;
child.setPressed(false);
setPressed(false);
if (!mDataChanged && !mIsDetaching && isAttachedToWindow()) {
performClick.run();
}
}
};
postDelayed(mTouchModeReset,
ViewConfiguration.getPressedStateDuration());
} else {
mTouchMode = TOUCH_MODE_REST;
updateSelectorState();
}
return;
} else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
performClick.run();
}
}
}
......
该省就省,我是省略代码切割符 ^_^
......
}

从上面代码的第 9 行可知。ListView 的 ItemView 的 hasFocusable 方法必须返回 fasle,才会运行 performClick.run(),才会运行到 OnItemClickListener 的 onItemClick 方法。

这也就是为什么通常我们在使用 ListView 的 OnItemClickListener 方法的时候要把 Item 布局文件的根节点的 descendantFocusability 属性设置为 blocksDescendants,而且该节点的 focusable 属性不能为 true。

最新文章

  1. C#使用Aspose.Cells导出Excel简单实现
  2. 关于表格前面checkbox复选框不打勾的问题
  3. UDP通讯程序设计---6
  4. 【转】ubuntu自动挂载硬盘方法
  5. NSURLConnection下载
  6. C++它tinyXML使用
  7. Python3基础 list() 将一个字符串转换成列表
  8. Android RoboGuice 使用指南
  9. 编程经验点滴----在 Oracle 数据库中保存空字符串
  10. jenkins发送生成的html报告作为邮件附件,但无内容的问题分析
  11. bzoj3514(LCT+主席树)
  12. pycharm 如何进行全部搜索
  13. c# 对文件操作
  14. PAT 1083 是否存在相等的差
  15. 读取文件任意位置的内容——RandomAccessFile
  16. xinetd黑/白名单配置教程(以telnet为例)
  17. dos命令:window10程序控制命令
  18. 算法导论 (Thomas H.Cormen / Charles E.Leiserson / Ronald L.Rivest / Clifford Stein 著)
  19. iOS9UICollectionView自定义布局modifying attributes returned by UICollectionViewFlowLayout without copying them
  20. List与数组的相互转换

热门文章

  1. 优动漫PAINT-牵牛花画法教程
  2. React中的AES加解密请求
  3. indexedDB介绍
  4. Python 中多线程之 _thread
  5. 用shell写一个简单DHCP配置脚本
  6. Django学习之配置篇
  7. MySQL数据类型及后面小括号的意义
  8. libTIFF 图像读取与保存
  9. [javase学习笔记]-7.6 thiskeyword的原理
  10. MongoDB查询、索引和聚合