android 焦点获取流程
来源:互联网 发布:如何安装管家婆软件 编辑:程序博客网 时间:2024/06/05 11:25
android一般都是手机或者平板,一般都是点击的时候获取焦点,当我们添加遥控或手柄支持焦点移动时,这个时候焦点的查找就比较明显了,那么Android的焦点是怎么查找的呢。
我们从handleImeFinishedEvent(ViewRootImpl.java)开始了解焦点的查找流程,handleImeFinishedEven是由dispatchImeFinishedEvent触发,dispatchImeFinishedEvent又是由InputMethodManager触发来的,
handleImeFinishedEvent中跟焦点相关的代码:
if (direction != 0) { View focused = mView.findFocus();//当前拥有焦点的控件 if (focused != null) { View v = focused.focusSearch(direction);//根据direction查找下一个应该获取焦点的控件 if (v != null && v != focused) { // do the math the get the interesting rect // of previous focused into the coord system of // newly focused view focused.getFocusedRect(mTempRect); if (mView instanceof ViewGroup) { ((ViewGroup) mView).offsetDescendantRectToMyCoords( focused, mTempRect); ((ViewGroup) mView).offsetRectIntoDescendantCoords( v, mTempRect); } if (v.requestFocus(direction, mTempRect)) {//请求焦点网 playSoundEffect(SoundEffectConstants .getContantForFocusDirection(direction)); finishInputEvent(q, true); return; } } // Give the focused view a last chance to handle the dpad key. if (mView.dispatchUnhandledMove(focused, direction)) {//以前的控件 焦点改变事件 finishInputEvent(q, true); return; } }
这里先获取当前焦点控件,然后根据direction获取下一个最佳的控件,获取控件后调用他的requestFocus,并给前面的焦点控件一个机会处理失去焦点事件,看一下focusSearch
public View focusSearch(int direction) { if (mParent != null) {//父控件不为空,调用它的focusSearch return mParent.focusSearch(this, direction); } else { return null; } }
一直调用parent的focusSearch,最终到
public View focusSearch(View focused, int direction) { if (isRootNamespace()) {//已经是Root层 (installDecor mDecor.setIsRootNamespace(true);) // 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) {//继续调用父控件的focusSearch return mParent.focusSearch(focused, direction); } return null; }
如果已经是根控件,调用FocusFinder的findNextFocus,最终调用它的findNextFocus
private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction) { View next = null; if (focused != null) { next = findNextUserSpecifiedFocus(root, focused, direction);//是xml里通过android:nextFocusUp="..."等或者代码特别指定的焦点顺序 } if (next != null) {//已经找到 return next; } ArrayList<View> focusables = mTempList;//mTempList try { focusables.clear(); root.addFocusables(focusables, direction);//获取所有可以获取焦点的控件 if (!focusables.isEmpty()) { next = findNextFocus(root, focused, focusedRect, direction, focusables);//查找下一个焦点控件 } } finally { focusables.clear(); } return next; }
先看一下该控件是否已经设置过它的焦点移动事件,indNextUserSpecifiedFocus就是干这个事的,此方法先去判断特定Id值是否存在,若存在则查询出Id对应的view.其实这些Id就是xml里通过android:nextFocusUp="..."等或者代码特别指定的焦点顺序.所以在此过程先判断,若存在,说明下个焦点已经找到,直接返回.,未找到,则调用findNextFocus继续查找
private View findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction, ArrayList<View> focusables) { if (focused != null) { if (focusedRect == null) { focusedRect = mFocusedRect;//焦点控件大小 } // fill in interesting rect from focused focused.getFocusedRect(focusedRect); root.offsetDescendantRectToMyCoords(focused, focusedRect); } else { if (focusedRect == null) { focusedRect = mFocusedRect; // make up a rect at top left or bottom right of root switch (direction) { case View.FOCUS_RIGHT: case View.FOCUS_DOWN: setFocusTopLeft(root, focusedRect); break; case View.FOCUS_FORWARD: if (root.isLayoutRtl()) { setFocusBottomRight(root, focusedRect); } else { setFocusTopLeft(root, focusedRect); } break; case View.FOCUS_LEFT: case View.FOCUS_UP: setFocusBottomRight(root, focusedRect); break; case View.FOCUS_BACKWARD: if (root.isLayoutRtl()) { setFocusTopLeft(root, focusedRect); } else { setFocusBottomRight(root, focusedRect); break; } } } } switch (direction) { case View.FOCUS_FORWARD: case View.FOCUS_BACKWARD: return findNextFocusInRelativeDirection(focusables, root, focused, focusedRect, direction); case View.FOCUS_UP: case View.FOCUS_DOWN: case View.FOCUS_LEFT: case View.FOCUS_RIGHT: return findNextFocusInAbsoluteDirection(focusables, root, focused,//根据方向查找 focusedRect, direction); default: throw new IllegalArgumentException("Unknown direction: " + direction); } }
调用findNextFocusInAbsoluteDirection查找下一个焦点控件
View findNextFocusInAbsoluteDirection(ArrayList<View> focusables, ViewGroup root, View focused, Rect focusedRect, int direction) {//获得焦点控件的位置矩阵.然后通过比较得到下一个焦点的控件 // initialize the best candidate to something impossible // (so the first plausible view will become the best choice) mBestCandidateRect.set(focusedRect);//设置mBestCandidateRect switch(direction) { case View.FOCUS_LEFT: mBestCandidateRect.offset(focusedRect.width() + 1, 0); break; case View.FOCUS_RIGHT: mBestCandidateRect.offset(-(focusedRect.width() + 1), 0); break; case View.FOCUS_UP: mBestCandidateRect.offset(0, focusedRect.height() + 1); break; case View.FOCUS_DOWN: mBestCandidateRect.offset(0, -(focusedRect.height() + 1)); } View closest = null; int numFocusables = focusables.size(); for (int i = 0; i < numFocusables; i++) {//查找最佳的焦点控件 View focusable = focusables.get(i); // only interested in other non-root views if (focusable == focused || focusable == root) continue; // get focus bounds of other view in same coordinate system focusable.getFocusedRect(mOtherRect);//获取当其拥有焦点时的区域大小 root.offsetDescendantRectToMyCoords(focusable, mOtherRect); if (isBetterCandidate(direction, focusedRect, mOtherRect, mBestCandidateRect)) {//比较和Best哪个更好 mBestCandidateRect.set(mOtherRect); closest = focusable;//更合适 } } return closest;//返回 }
根据焦点控件的区域去查找一个合适的,具体查找,比较那个合适比较复杂,暂时还没看懂。
关于移动的时候有时候没有焦点,我们可以查看在findNextFocus(ViewGroup root, View focused, Rect focusedRect, int direction)这个函数中,root.addFocusables(focusables, direction);/可能获取到了很多有焦点的控件,最后找到的合适的控件可能不是我们想要的,这时我们可以把某些控件设置为不能获取焦点,这样我们移动焦点时,可能是我们想要的焦点(偷懒的做法)
mDaySpinner.setFocusable(false); mMonthSpinner.setFocusable(false); mYearSpinner.setFocusable(false); mYearSpinnerInput.setSelection(0, 4); //获取焦点时选中的text
- android 焦点获取流程
- android控件获取焦点
- android 空间获取焦点
- android editText 获取焦点
- Android 获取音频焦点
- Android控件获取焦点
- Android焦点分发基本流程
- Android EditText获取焦点失去焦点监听
- android 关于获取焦点问题
- android ListItem 焦点获取问题
- Android View如何获取焦点
- Android View如何获取焦点
- Android View如何获取焦点
- Android AudioManager获取媒体焦点
- Android开发:Button获取焦点
- android 对话框获取焦点问题
- Android View如何获取焦点
- Android AudioManager获取媒体焦点
- 非常简单且易错的java Demo
- 关于Hbase的cache配置
- Android发送通知
- jpa学习笔记
- MD5加密解密帮助类
- android 焦点获取流程
- poj1258--最小生成树prim算法实现
- ecmai用户不成功问题(有点像登录成功了但是登录状态不改变,其实是登录成功后自动退出)
- VMware接入Openstack方案分析
- BeanDefinitionParserDelegate解读
- [LeetCode系列]卡特兰数(Catalan Number) 在求解独特二叉搜寻树(Unique Binary Search Tree)中的应用分析
- c#端口扫描器源代码
- 权重随机抽取
- opengl 来画个三角形