19

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

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

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

在此处输入图像描述

我的解决方案是在适配器中有两种布局(一种用于 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;
    }

结果是:

在此处输入图像描述

我根据行是偶数还是奇数来镜像行。现在,我的问题是如何根据名称镜像 UI。我想我应该将条款条件从更改if(position % 2 == 0)if(isNameLTR(FIRST_CHAR_OF_NAME)). 我不知道如何实现这个方法。

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

任何建议或意见将不胜感激。谢谢

4

3 回答 3

35

解决方案,比我想的更容易:) 感谢 JAVA

比迪课。此类具有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);

...

结果是:

在此处输入图像描述

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

更新

还有另一种方法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);
于 2013-08-02T04:01:25.797 回答
4

如果文本在 a 中TextView,那么您所要做的就是

android:textDirection="anyRtl"

强制 RTL。根据您的要求查看其他选项。

在某些情况下,混合语言文本不会显示在TextView. 例如,文本可能会以共享的形式传递Intent给 Gmail 或 WhatsApp 等。在这种情况下,您必须使用以下类的组合:

正如文档中所引用的,这些是...

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

因此,例如,假设您有一个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。如果您希望字符串是 RTL,即使它完全使用,比如英语(一种 LTR 语言),那么您可以使用TextDirectionHeuristics.RTL而不是TextDirectionHeuristics.ANYRTL_LTR.

这是在没有TextView. 有趣的是,正如文档所述,

另请注意,这些方向启发式对应于类中提供的相同类型的常量ViewsetTextDirection()例如TEXT_DIRECTION_RTL.

更多参考资料:

1. 编写阿拉伯文和英文混合的文本文件

2.Unicode 双向算法

于 2016-11-15T06:01:28.853 回答
0

使用textAlignmentwithgravity获取所有文本RIGHTLEFT

android:gravity="right"
android:textAlignment="gravity"
于 2013-12-15T05:27:32.510 回答