光华网视台

[Android学习笔记]理解焦点处理原理的相关记录

主页 > 法治 > 焦点 > [Android学习笔记]理解焦点处理原理的相关记录 2017-07-10 00:18:23 来源:网络整理



以下所涉及的焦点部分,只是按键移动部分,不明确包含Touch Focus部分

需解决问题

控件的下一个焦点是哪?

分析思路

当用户通过按键(遥控器等)触发焦点切换时,事件指令会通过底层进行一系列处理。
在ViewRootImpl.java中有一个方法,deliverKeyEventPostIme(...),因为涉及到底层代码,所以没有详细的跟踪分析此方法的调用逻辑,根据网上的资料,按键相关的处理会经过此方法。

private void deliverKeyEventPostIme(QueuedInputEvent q) { ... // Handle automatic focus changes. if (event.getAction() == KeyEvent.ACTION_DOWN) { int direction = 0; switch (event.getKeyCode()) { case KeyEvent.KEYCODE_DPAD_LEFT: if (event.hasNoModifiers()) { direction = View.FOCUS_LEFT; } break; case KeyEvent.KEYCODE_DPAD_RIGHT: if (event.hasNoModifiers()) { direction = View.FOCUS_RIGHT; } break; ... } if (direction != 0) { View focused = mView.findFocus(); if (focused != null) { View v = focused.focusSearch(direction); if (v != null && v != focused) { ..... if (v.requestFocus(direction, mTempRect)) { ...finishInputEvent(q, true); return; } } ... } }

由此方法可以看出,最主要的两个核心过程:

View v = focused.focusSearch(direction); v.requestFocus(direction, mTempRect)

接下来详细的分析下,看看过程中进行了什么操作

具体分析

在具体分析前,首先我们先明确下相关变量的定义

View mView : 主体View[DecorView]

//一般把主View“DecorView”添加到WindowManagerImpl中(通过addView) //WindowManagerImpl.java private void addView(View view...) { ViewRootImpl root; root = new ViewRootImpl(view.getContext()); ... root.setView(view, wparams, panelParentView); ... } //ViewRootImpl.java public void setView(View view....) { synchronized (this) { if (mView == null) { mView = view; ... } ... } }

所以mView是一个DecorView类型的变量.

View focused :

View focused = mView.findFocus(); //PhoneWindow.java private final class DecorView extends FrameLayout implements RootVie.... { ... } //FrameLayout.java public class FrameLayout extends ViewGroup { ... } //ViewGroup.java //mFocused记录的是当前被焦点选中的view @Override public View findFocus() { if (DBG) { System.out.println("Find focus in " + this + ": flags=" + isFocused() + ", child=" + mFocused); } if (isFocused()) { return this; } if (mFocused != null) { return mFocused.findFocus(); } return null; }

所以最终得到的focused为当前页面中得到焦点的view.

在明确的相关变量后,我们开始View v = focused.focusSearch(direction)的具体分析.

//View.java public View focusSearch(int direction) { //如果存在父控件,则执行父控件的focusSearch方法 if (mParent != null) { return mParent.focusSearch(this, direction); } else { return null; } } //ViewGroup.java public View focusSearch(View focused, int direction) { //判断是否为顶层布局,若是则执行对应方法,若不是则继续向上寻找,说明会从内到外的一层层进行判断,直到最外层的布局为止 if (isRootNamespace()) { return FocusFinder.getInstance().findNextFocus(this, focused, direction); } else if (mParent != null) { return mParent.focusSearch(focused, direction); } return null; }

说明在这个过程中,其实是从里层开始一直遍历到最外层布局,然后在最外层布局将处理交给了FocusFinder中的方法.

FocusFinder.getInstance().findNextFocus(this, focused, direction);

那我们来看看此方法具体做了什么操作

相关视频

当前排行

  • 栏目:焦点
  • 作者:采集侠