android focus 查找

在焦点模式下,当我们按下方向键的时候,android系统就会调用当前焦点控件的focusSerach方法,找到下一个焦点的控件,并把焦点赋给它。

一般情况下,Android系统查找的焦点,是以中心点为依据(没有看源码,从平常操作的感觉是这样),按指定的方向,找到距离当前控件中心点最近的下一个控件。

通常这正是我们需要的焦点顺序。但是,凡是总有例外。有时候我们想要的焦点顺序和系统查找的顺序不一致,这时候,有什么办法吗?

以下介绍两种方法:

一、当我们明确知道,下一个获取焦点的控件时,可以调用setNextFocusUpId()的方法(当然,还有对应的setNextFocusDownId,setNextFocusLeftId,setNextFocusRightId等方法)。系统查找下一个焦点的时候,就会返回我们设置id的那个控件。

二、当我们无法知道下一个控件的ID的时候,可以重写focusrSearch方法。

       这种方法就比较复杂了,需要根据实际情况来改写,当然,需要了解focusSearch的原理,才能改写。

      ok,开始分析focusSearch的原理。

      来看一下focusSearch的时序图:


分为以下步骤:

  1、按下方向键的时候,系统就会调用到当前焦点的searchFocus(int direction)方法。源码如下:

    public View focusSearch(@FocusRealDirection int direction) {
        if (mParent != null) {
            return mParent.focusSearch(this, direction);
        } else {
            return null;
        }
    }

2、从上面代码第三句代码中可以看到,它会调用parent(ViewGroup)的focusSearch(View focused,int ditection)的方法。源码如下:

    public View focusSearch(View focused, int direction) {
        if (isRootNamespace()) {
            // root namespace means we should consider ourselves the top of the
            // tree for focus searching; otherwise we could be focus searching
            // into other tabs.  see LocalActivityManager and TabHost for more info
            return FocusFinder.getInstance().findNextFocus(this, focused, direction);
        } else if (mParent != null) {
            return mParent.focusSearch(focused, direction);
        }
        return null;
    }

3,先看上面代码第8行,如果当前节点还不是根节点的话,就调用父节点的focusSearch继续查找,直到根节点为止(第6行)。在根节点调用

findNextFocus(ViewGroup root, View focused, int direction)的方法,并把根节点赋值给它。

    public final View findNextFocus(ViewGroup root, View focused, int direction) {
        return findNextFocus(root, focused, null, direction);
    }
    private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) {
        View next = null;
        if (focused != null) {
            next = findNextUserSpecifiedFocus(root, focused, direction);
        }
        if (next != null) {
            return next;
        }
        ArrayList<View> focusables = mTempList;
        try {
            focusables.clear();
            root.addFocusables(focusables, direction);
            if (!focusables.isEmpty()) {
                next = findNextFocus(root, focused, focusedRect, direction, focusables);
            }
        } finally {
            focusables.clear();
        }
        return next;
    }
第二段代码的第4行,就是先查找用户设置的nextFocus。即第一种方法设置的setNextFocusUpId等。

接下来就是按照算法查找下一个焦点,现在还没有必要完全了解。


从上面的分析中,有两个重点需要注意:

1、focusSearch只是查找下一个获取焦点的控件,但改控件还未获取焦点(需要调用requestFocus后才能获取焦点)。

     所以,可以充值focusSearch的方法,来选择自己需要的下一个焦点。

2、注意看这个方法:FocusFinder.getInstance().findNextFocus(ViewGroup root, View focused, int direction).它的第一个参数是ViewGruop,所以,如果你需要限定在某个ViewGruop中查找控件,就可以在focusSeach中调用这个方法。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值