2018年12月4日 星期二

Android Focus一些概念

android提供了一些焦点相关的属性,在现有的框架层下通过设置View的属性来获得焦点:
  • android:focusable:设置一个控件能否获得焦点
  • android:nextFocusDown:(当按下键时)下一个获得焦点的控件
  • android:nextFocusDown:(当按下键时)下一个获得焦点的控件
  • android:nextFocusLeft:(当按下键时)下一个获得焦点的控件
  • android:nextFocusRight:(当按下键时)下一个获得焦点的控 **注意:**如果按下某个方向键时,想让焦点停留在自身,可以使用android:nextFocusRight:"@null"或者android:nextFocusRight:"@id/自身id"
這只有在對view是有效的,對viewgroup等類是無效的 原因在於

private View findNextUserSpecifiedFocus(ViewGroup root, View focused, int direction) {
// check for user specified next focus
View userSetNextFocus = focused.findUserSetNextFocus(root, direction);
View cycleCheck = userSetNextFocus;
boolean cycleStep = true; // we want the first toggle to yield false
while (userSetNextFocus != null) {
if (userSetNextFocus.isFocusable()
&& userSetNextFocus.getVisibility() == View.VISIBLE
&& (!userSetNextFocus.isInTouchMode()
|| userSetNextFocus.isFocusableInTouchMode())) {
return userSetNextFocus;
}
userSetNextFocus = userSetNextFocus.findUserSetNextFocus(root, direction);
if (cycleStep = !cycleStep) {
cycleCheck = cycleCheck.findUserSetNextFocus(root, direction);
if (cycleCheck == userSetNextFocus) {
// found a cycle, user-specified focus forms a loop and none of the views
// are currently focusable.
break;
}
}
}
return null;
} 他在搜尋usersetnextfocus是用該focus view去找的 viewgroup自然對於該function就無作用。


一般來說focusSearch是focus主要的來源,如果都不override他就是一路找到decorView?或許吧,使用FocusSearchInstance來找,那個Util會把子Views focusable的全找出來作排序用rect的方式去找最靠近的focus, 除非你有指定id. 原生的四大主件LinearLayout RelativeLayout ...全都沒有複寫這method. 只有Leanback library的元件才有,所以客製化的頁面UI幾乎全都要自己override這method來控制focus。至少我認為是這樣。

@Overridepublic View focusSearch(View focused, int direction) {
    View returnView = null;
    ViewParent trace = focused.getParent();
    while (trace != null) {
        if (trace instanceof SlidingTabLayout) {
            returnView = FocusFinder.getInstance().findNextFocus((ViewGroup) trace, focused, direction);            break;        } else if (trace instanceof ViewPager) {
            returnView = FocusFinder.getInstance().findNextFocus((ViewGroup) trace, focused, direction);            break;        }
        trace = trace.getParent();    }

    if (trace instanceof SlidingTabLayout && direction == View.FOCUS_DOWN) {
        return pager;    }

    if (trace instanceof ViewPager && direction == View.FOCUS_UP) {
        return tabs.getSelectedView();    }

    return returnView == null ? super.focusSearch(focused, direction) : returnView;}

以上是一些客製化的範例。

沒有留言:

張貼留言