android右到左布局未能切换_android 4.2的新特性layoutRtl,让布局自动从右往左显示...

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 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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值