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


转载于:https://my.oschina.net/benzhang99/blog/157060

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Android中,您可以使用以下方法来确定文本的方向从右: 1.在XML布局文件中,在TextView或EditText标记中添加android:textDirection属性,将其设置为rtl。 例如: ``` <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="你好世界" android:textDirection="rtl"/> ``` 2.在Java代码中,使用setTextDirection()方法来设置TextView或EditText的文本方向。 例如: ``` TextView textView = findViewById(R.id.text_view); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { textView.setTextDirection(View.TEXT_DIRECTION_RTL); } textView.setText("你好世界"); ``` 以上两种方法都将文本从右显示。如果您需要在应用程序中使用从右的文本,这些方法应该可以满足您的需求。 ### 回答2: 在Android中,可以通过以下方法来判断文本是否应该从右排列显示: 使用`TextUtils`工具类的`getLayoutDirectionFromLocale(Locale locale)`方法来获取指定语言的布局方向。这个方法会根据语言的阅读方向返回一个常量:`View.LAYOUT_DIRECTION_LTR`表示从到右排列(默认的文本排列方向),`View.LAYOUT_DIRECTION_RTL`表示从右排列。 示例代码如下: ``` Locale locale = Locale.getDefault(); // 获取当前设备的默认语言 int layoutDirection = TextUtils.getLayoutDirectionFromLocale(locale); if (layoutDirection == View.LAYOUT_DIRECTION_RTL) { // 需要从右排列的逻辑处理 ... } else { // 默认的从向右排列逻辑 ... } ``` 以上是一种判断文本布局方向的方法。根据实际需要,可以在相应的地方使用该方法,来对从右排列的情况进行处理,例如在绘制UI界面、处理文字对齐等方面。 ### 回答3: 在Android中,可以使用`Bidi`类的`isRtl()`方法来判断文本是否需要从右排列显示。 首先,需要添加`androidx.core.text.BidiFormatter`库的依赖。 然后,在代码中调用`Bidi`类的`isRtl()`方法,将待判断的文本作为参数传入该方法。`isRtl()`方法会返回一个布尔值,表示文本是否需要从右排列显示。 以下是一个示例代码: ```java import androidx.core.text.BidiFormatter; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String text = "مرحبا بك"; // 待判断的文本 boolean isRtl = BidiFormatter.getInstance().isRtl(text); if (isRtl) { // 文本需要从右排列显示 // 在此处添加相关逻辑或调整显示样式 } else { // 文本不需要从右排列显示 // 在此处添加相关逻辑或调整显示样式 } } } ``` 在示例代码中,我们将文本 `"مرحبا بك"` 作为待判断的文本传入`isRtl()`方法。如果返回值为`true`,则表示该文本需要从右排列显示。可以根据实际情况在相应的逻辑中处理文本的显示方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值