如何在Android中获取文本方向并根据方向动态更改布局?

19

我正在研究根据文字方向动态更改UI的可行性。虽然Google支持RTL语言(参考:Android 4.2中的本地RTL支持),但它并没有涵盖应用程序具有LTR和RTL内容混合的情况。

如果我们有多语言应用程序,并且它具有不同语言的静态数据源(如菜单项),那么Google的解决方案是正确的。然而,我没有找到其他关于如何根据文本内容的方向动态更改布局的文档。

下面的图片显示了我的测试应用程序的当前设计。列表来自Facebook(我的朋友列表),包含英语和波斯尼亚语名称。

enter image description here

我的解决方案是在适配器中拥有两个布局(一个LTR和一个RTL),并根据名称的方向分配每个布局。因此,我编写了以下代码:

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

            if(position % 2 == 0)
                convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
            else
                convertView = myInflater.inflate(R.layout.list_add_friends_row_mirror, null);

            holder = new ViewHolder();

            holder.llSection = (LinearLayout) convertView.findViewById(R.id.section);
            holder.tvUserName = (TextView) convertView.findViewById(R.id.tvUserName);
            holder.ivPicture = (ImageView) convertView.findViewById(R.id.ivPicture);
            holder.btnAdd = (Button) convertView.findViewById(R.id.btnAdd);

            convertView.setTag(holder);



        holder.btnAdd.setTag(position);
        holder.tvUserName.setText(userList.get(position).getName());
        imageDownloader.displayImage(holder.ivPicture, userList.get(position).getPhotoUrl());

        ...

        return convertView;
    }

结果是:

enter image description here

我根据行号的奇偶性进行了镜像。现在,我的问题是如何基于名称反转UI。 我认为我应该将条件从if(position % 2 == 0)更改为类似if(isNameLTR(FIRST_CHAR_OF_NAME))的条件语句。但我不知道如何实现此方法。

如何知道字符是LTR还是RTL?(我认为Android知道单词的第一个字符是RTL或LTR,这就是为什么当文本视图的宽度与父视图相匹配时,如果字符是RLT,则将文本对齐到右侧,而如果字符是LTR,则将其对齐到左侧)。

任何建议或评论将不胜感激。谢谢

3个回答

37

解决方案比我想象的要简单 :) 多亏了JAVA

有一个Bidi类。这个类有一个getBaseLevel()方法,如果文本是从左到右,则返回0,否则返回1(如果是从右到左)。

所以,这是我的代码:

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        Bidi bidi = new Bidi(userList.get(position).getName(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
        if(bidi.getBaseLevel() == 0)
            convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
        else
            convertView = myInflater.inflate(R.layout.list_add_friends_row_mirror, null);

...

并且结果为:

enter image description here

=============

更新:

还有另一种方法,baseIsLeftToRight(),也许更适合在if语句中使用。结果与上面相同。

Bidi bidi = new Bidi(userList.get(position).getName(), Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
if(bidi.baseIsLeftToRight())
                convertView = myInflater.inflate(R.layout.list_add_friends_row, null);
            else
                convertView = myInflater.inflate(R.layout.list_add_friends_row_mirror, null);

4
如果文本在TextView中,那么你所需要做的就是:
android:textDirection="anyRtl"

要强制RTL。查看其他选项以满足您的要求。

可能有情况下,混合语言文本不应该显示在TextView中。例如,文本可能会通过分享Intent传递到Gmail或WhatsApp等应用程序中。在这种情况下,您必须使用以下类的组合:

正如文档中所述,这些是...

实用程序类,用于在潜在相反方向性上下文中格式化文本以进行显示而不会搞乱。上下文的方向性在格式化程序创建时设置,文本的方向性可以在估计或已知时传入。

例如,假设您有一个包含英语和阿拉伯语组合的String,并且您需要将文本设置为

  • 从右到左(RTL)。
  • 始终右对齐,即使句子以英语开头。
  • 正确顺序且不混淆的英文和阿拉伯语单词。

然后您可以使用unicodeWrap()方法来实现这一点,如下所示:

String mixedLanguageText = ... // mixed-language text

if(BidiFormatter.getInstance().isRtlContext()){
    Locale rtlLocale = ... // RTL locale
    mixedLanguageText = BidiFormatter.getInstance(rtlLocale).unicodeWrap(mixedLanguageText, TextDirectionHeuristics.ANYRTL_LTR);
}

如果字符串中有至少一个RTL语言字符,则将其转换为RTL并向左对齐,否则回退到LTR。如果您希望字符串即使完全以英语(LTR语言)为例也是RTL,则可以使用TextDirectionHeuristics.RTL而不是TextDirectionHeuristics.ANYRTL_LTR。这是在没有TextView的情况下处理混合方向文本的正确方式。有趣的是,正如文档所述,这些方向启发式与View类提供的setTextDirection()相同类型的常量相对应,例如TEXT_DIRECTION_RTL进一步参考: 1. 写混合阿拉伯语和英语文本文件2. Unicode双向算法

0
使用textAlignmentgravity来使所有文本右对齐左对齐
android:gravity="right"
android:textAlignment="gravity"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接