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

时间:2013-08-02 03:18:22

标签: android internationalization bidi

我正在研究基于文本方向动态更改UI的可行性。虽然Google支持RTL语言(参考:Native RTL support in Android 4.2),但它不包括应用程序混合了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 个答案:

答案 0 :(得分:26)

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

Bidi课程。这个类有getBaseLevel() method,如果你的文字从左到右,则返回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);

答案 1 :(得分:3)

如果文字位于TextView,那么您只需要

android:textDirection="anyRtl"

强制RTL。请参阅其他选项以满足您的要求。

有时可能会在TextView中显示混合语言文字。例如,文本可以在共享Intent中传递到Gmail或WhatsApp,依此类推。在这种情况下,您必须使用以下类的组合:

正如文档中引用的那样......

  

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

例如,假设您有一个String,其中包含英语和英语的组合。阿拉伯语,你需要文字

  • 从右向左 (RTL)。
  • 始终 右对齐 ,即使句子以英文开头。
  • 英语&amp;阿拉伯语单词的顺序正确,没有乱花。

然后您可以使用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的情况下处理混合方向文本的正确方法。有趣的是,正如文档所述,

  

另请注意,这些方向启发式对应于View的{​​{1}}类中提供的相同类型的常量,例如setTextDirection()

进一步参考:

1。 Write text file mix between arabic and english

2。 Unicode Bidirectional Algorithm

答案 2 :(得分:0)

textAlignmentgravity一起使用,以获取所有文字 RIGHT LEFT

android:gravity="right"
android:textAlignment="gravity"