这篇文章使用一个demo来描述一下android焦点分发的基本流程,描述一下我们一个控件请求焦点到我们切换焦点的时候走的是怎么样一个流程,要是对android的焦点的基础不了解的请看我前面的文章:Android焦点分发基础,先对android焦点有一个感性得认识。

首先我需要先自定义FocusButton、FocusLinearLayout和FocusRelativeLayout三个控件,主要就是重写里面的findFocus、requestFocus、requestChildFocus和focusSearch这几个方法,当然Button是没有requestChildFocus这个方法的。下面给出FocusLinearLayout的代码,其余两个跟这个一样的,最后会给出demo代码的。

package view.danxx.com.focustest;import android.content.Context;import android.graphics.Rect;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.widget.LinearLayout;/*** Created by Danxingxi on 2016/4/3.*/public class FocusLinearLayout extends LinearLayout {  private final static String TAG = "danxx";  private final static String LogTag = "FLL-->";  public FocusLinearLayout(Context context) {    super(context);  }  public FocusLinearLayout(Context context, AttributeSet attrs) {    super(context, attrs);  }  public FocusLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);  }  @Override  public View findFocus() {    Log.d(TAG , LogTag+"findFocus");    return super.findFocus();  }  @Override  public boolean requestFocus(int direction, Rect previouslyFocusedRect) {    Log.d(TAG , LogTag+"requestFocus");    return super.requestFocus(direction, previouslyFocusedRect);  }  @Override  public void requestChildFocus(View child, View focused) {    super.requestChildFocus(child, focused);    Log.d(TAG, LogTag + "requestChildFocus");  }  @Override  public View focusSearch(View focused, int direction) {    Log.d(TAG, LogTag + "focusSearch");    return super.focusSearch(focused, direction);  }}

下面一张图描述了布局关系:

Android焦点分发基本流程_第1张图片

我们在MainActivity中直接把FocusButton1请求焦点

Android焦点分发基本流程_第2张图片

接下来看看打印出来的日志信息:

Log TAG对应关系:

TBtn :FocusButton

FRL: FocusRelativeLayout

FLL: FocusLinearLayout

Android焦点分发基本流程_第3张图片

可以看到,焦点请求(requestFocus)是从父容器向下寻找的,焦点的寻找(findFocus)也是从父容器向下寻找。

上面是我们使FocusButton1主动请求获取焦点,下面我们试试不主动获取焦点会怎么样:

Android焦点分发基本流程_第4张图片

其实还是FocusButton1获得了焦点,只是FocusButton1获得焦点是系统自己执行的,系统自动请求焦点也是从最顶层的容器控件开始向内请求的,我们进入一个界面系统会自动请求焦点,寻找焦点,最后使用一个控件获得焦点。


我们再尝试一下切换焦点,看看focusSearch是怎么工作的,我们把焦点向下按到第二个按钮。

Android焦点分发基本流程_第5张图片

看看Log信息:

Android焦点分发基本流程_第6张图片

我们可以看到,切换焦点的时候,也是要从最顶层的父容器寻找到焦点(findFocus),然后从获得到焦点的控件开始从内向外调用focusSearch寻找下一个焦点控件。

总结:Android的焦点分发跟事件分发类似,有一个从内向外,从外向内的过程,焦点分发中,寻找当前的焦点控件(findFocus)和焦点的请求(requestChildFocus)都是从外向内的,就是从顶层的父容向内层的子容器寻找和请求,但是搜寻下一个焦点(focusSearch)是从当前焦点控件开始的,就是从内向外寻找,到这里我们知道了Android焦点分发的一个基本流程,但是还不知道焦点分发的原理,后面我会写一篇《Android焦点分发原理》来分析为啥是这样的一个流程。下一篇文章会介绍findFocus、requestFocus、requestChildFocus和focusSearch这几个方法。


思考:既然焦点分发是层层传递的,我就可以拦截焦点分发,可以代替系统来自定义我们的焦点跳转,自定义一个容器layout,写上两个接口,在重写的focusSearch方法中调用对应的接口方法,这样我就可以操控焦点 分发,其实系统提供了setNextFocusDownId类似的方法,可以简单地控制焦点,但是这样不是很灵活。

更多相关文章

  1. Android SDCard Mount 流程分析(一)
  2. Android实现画虚线的控件
  3. Android TextView背景跟随焦点的变化
  4. Android EditText 自动获取焦点,并弹出键盘
  5. Android:控件的对象修改控件的值
  6. ScrollView嵌套webview因焦点问题导致自动滑动
  7. 【转】Android kernel启动流程
  8. android之datepicker控件用法
  9. 如何让EditText不自动获取焦点

随机推荐

  1. ubuntu20 源码安装nginx以及常用命令
  2. JavaScript中的流程控制与函数
  3. JS初识变量及函数学习
  4. html测试题小结
  5. Java使用JDBC连接数据库的详细步骤
  6. rem+vw布局的原理与rem的设置技巧
  7. JS函数类型与数据类型学习
  8. JS:变量和函数介绍
  9. JS基础学习:工具、变量与命名
  10. js 作用域与常量