android4.2有一个新特性 layoutRtl,当然是对于开发者而言的,主要是方便开发者去支持阿拉伯语/波斯语等阅读习惯是从右往左的。

可以在manifest的application标签添加:android:supportsRtl取值:true/false

这样就可以打开layoutRtl这个功能。如果当前系统语言是阿拉伯语/波斯语,打开了这个功能的应用的布局就会自动变成从右往左的,当然前提是布局没有写死控件间的位置。

layoutRtl这个功能主要是在ViewGroup的子类ViewRootImpl在控制,具体怎么实现,还是需要自己去看看代码,

如果布局变成了从右往左的话,焦点的移动也会有一些变化。EditText有一个标签是用来让输入法提供类似“next”的按钮的:imeoptions=“actionNext”。你按“next”的时候会发现,本来应该往右/下移动的光标,变成往左/上移动。

View焦点(focus)的控制方向是由FocuseFinder类进行控制的。你按下“next”的事件会由TextView的onEditorAction()进行处理。

public void onEditorAction(int actionCode) {        final Editor.InputContentType ict = mEditor == null ? null : mEditor.mInputContentType;        if (ict != null) {            if (ict.onEditorActionListener != null) {                if (ict.onEditorActionListener.onEditorAction(this,                        actionCode, null)) {                    return;                }            }            // This is the handling for some default action.            // Note that for backwards compatibility we don't do this            // default handling if explicit ime options have not been given,            // instead turning this into the normal enter key codes that an            // app may be expecting.            if (actionCode == EditorInfo.IME_ACTION_NEXT) {                View v = focusSearch(FOCUS_FORWARD);                if (v != null) {                    if (!v.requestFocus(FOCUS_FORWARD)) {                        throw new IllegalStateException("focus search returned a view " +                                "that wasn't able to take focus!");                    }                }                return;            } else if (actionCode == EditorInfo.IME_ACTION_PREVIOUS) {                View v = focusSearch(FOCUS_BACKWARD);                if (v != null) {                    if (!v.requestFocus(FOCUS_BACKWARD)) {                        throw new IllegalStateException("focus search returned a view " +                                "that wasn't able to take focus!");                    }                }                return;            } else if (actionCode == EditorInfo.IME_ACTION_DONE) {                InputMethodManager imm = InputMethodManager.peekInstance();                if (imm != null && imm.isActive(this)) {                    imm.hideSoftInputFromWindow(getWindowToken(), 0);                }                return;            }        }        ViewRootImpl viewRootImpl = getViewRootImpl();        if (viewRootImpl != null) {            long eventTime = SystemClock.uptimeMillis();            viewRootImpl.dispatchKeyFromIme(                    new KeyEvent(eventTime, eventTime,                    KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0,                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0,                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE                    | KeyEvent.FLAG_EDITOR_ACTION));            viewRootImpl.dispatchKeyFromIme(                    new KeyEvent(SystemClock.uptimeMillis(), eventTime,                    KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0,                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0,                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE                    | KeyEvent.FLAG_EDITOR_ACTION));        }    }


最终会调用FocuseFinder类的findNextFocus()方法来查找下一个可以获得focus的view。

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://这里root是ViewRootImpl的实例                        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);        }    }
private void setFocusBottomRight(ViewGroup root, Rect focusedRect) {        final int rootBottom = root.getScrollY() + root.getHeight();        final int rootRight = root.getScrollX() + root.getWidth();        focusedRect.set(rootRight, rootBottom, rootRight, rootBottom);    }    private void setFocusTopLeft(ViewGroup root, Rect focusedRect) {        final int rootTop = root.getScrollY();        final int rootLeft = root.getScrollX();        focusedRect.set(rootLeft, rootTop, rootLeft, rootTop);    }
具体可以自己看代码,上面的类名都添加了超链接到github


更多相关文章

  1. Android(安卓)培训计划:如何从功能机时代的 C/C++ 工程师转型至 A
  2. android实现简单音乐播放器
  3. 分享五种Android常用布局方式
  4. 【项目】Android(安卓)预置第三方应用可卸载功能的实现
  5. 第16章、布局Layouts之GridLayout网格布局(从零开始学Android)
  6. Android(安卓)实现视屏播放器、边播边缓存功能,附源码
  7. Android(安卓)studio 通过xml文件设置点击按钮按钮时更换背景,松
  8. Android(安卓)真机布局查看
  9. android简单网页浏览器的开发

随机推荐

  1. Android(安卓)ANR 分析学习总结(转)
  2. github开源库(三)
  3. Android(安卓)Studio集成友盟APP统计
  4. android pop3与imap方式接收邮件(javamail
  5. Android(安卓)Studio中LogCat Filter的设
  6. Android(安卓)MediaCodec参数笔记
  7. android 删除整个文件夹里面的文件
  8. Android开启闪光灯的方法 Android打开手
  9. Android下载文件,如果文件夹下有同名文件,
  10. android 布局: LinearLayout如何使TextVie