Android阿拉伯语混排

1.Android阿拉伯语混排显示关键类 BidiFormatter

关于这个类的具体使用大家可以阅读一下官方文档
BidiFormatter

阿拉伯语的显示阅读方式都是自右向左的,与我们熟悉的自左向右刚好相反。

为了便于讲解,我这里把代码和显示效果一起结合说明。

下面要用到的方法
import androidx.core.text.BidiFormatter

fun String.biDiFormat(): String {
       return BidiFormatter.getInstance(Locale.getDefault())
            .unicodeWrap(this, TextDirectionHeuristicsCompat.LOCALE)
    }

这里注意用到androidx.core.text
还有一个相同类是在android.text包下的,但是它的unicodeWrap方法只能在android8.0以上才可以使用。

1.示例一
测试一
  val content = "我是中国人"
  binding.tv.text = content

在系统语言是自左向右环境下显示如下
在这里插入图片描述

在系统语言是自右向左下显示如下
在这里插入图片描述

第一张图是自左向右环境下显示是没有问题的
第二张图你是不是觉得也没什么问题呢?
光从文字上看确实是没什么问题,但是我们在系统语言是自右向左的阅读方式下显示时,
那这就是问题了,正常显示的话文本应该是位于屏幕右侧,那怎么实现这个效果呢。如下:

  val content = "我是中国人"
  binding.tv.text = content.biDiFormat()

在系统语言是自右向左下显示如下
在这里插入图片描述

此时的显示才是正确的效果。

测试二
val stringBuffer = StringBuffer()
stringBuffer.append("يبيب")
stringBuffer.append("中国人")
binding.tv.text = stringBuffer.toString()

在系统语言是自左向右下显示如下
在这里插入图片描述
在系统语言是自右向左环境下显示如下
在这里插入图片描述

此时的第二张图显示效果是没有问题的,因为系统语言是自右向左下,文本显示也是位于屏幕右侧,阅读方式也是从右往左。我们在看第一张图,文本在系统语言是自左向右环境下位于屏幕右侧,读取方式也是从右往左,正常情况下文本显示是在屏幕左侧,阅读方式也是从左往右。为了修改这个问题使用修改方法同上:

val stringBuffer = StringBuffer()
stringBuffer.append("يبيب")
stringBuffer.append("中国人")
binding.tv.text = stringBuffer.toString().biDiFormat()

在系统语言是自左向右环境下显示如下
在这里插入图片描述

此时的显示才是正确的效果。

测试三
val stringBuffer = StringBuffer()
stringBuffer.append("中国人")
stringBuffer.append("يبيب")
binding.tv.text = stringBuffer.toString()

在系统语言是自左向右环境下显示如下
在这里插入图片描述

在系统语言是自右向左下显示如下
在这里插入图片描述

分析同测试一和测试二,图一显示没有问题,
图二显示文本应该是靠右边,而且两个文本的位置也是相反了。
那么要修改这个问题方式同上

测试三
val stringBuffer = StringBuffer()
stringBuffer.append("中国人")
stringBuffer.append("يبيب")
binding.tv.text = stringBuffer.toString().biDiFormat()

在系统语言是自右向左下显示如下
在这里插入图片描述

此时的显示才是正确的效果。

测试四
val stringBuffer = StringBuffer()
stringBuffer.append("我是")
stringBuffer.append("يبيب")
stringBuffer.append("中国人")
binding.tv.text = stringBuffer.toString()

在系统语言是自左向右环境下显示如下
在这里插入图片描述

在系统语言是自右向左下显示如下
在这里插入图片描述

分析同上,图一显示没有问题;
图二显示文本应该是靠右边,而且两个文本的位置也是相反了。
那么要修改这个问题方式同上:

val stringBuffer = StringBuffer()
stringBuffer.append("我是")
stringBuffer.append("يبيب")
stringBuffer.append("中国人")
binding.tv.text = stringBuffer.toString().biDiFormat()

在系统语言是自右向左下显示如下
在这里插入图片描述

此时的显示才是正确的效果。

测试五
val stringBuffer = StringBuffer()
stringBuffer.append("يسيي")
stringBuffer.append("中国人")
stringBuffer.append("يبيب")
binding.tv.text = stringBuffer.toString()

在系统语言是自左向右环境下显示如下
在这里插入图片描述

在系统语言是自右向左下显示如下
在这里插入图片描述

分析同上,图二显示没有问题;
图一显示文本应该是靠左边,而且两个文本的位置也是相反了。
那么要修改这个问题方式同上:

val stringBuffer = StringBuffer()
stringBuffer.append("يسيي")
stringBuffer.append("中国人")
stringBuffer.append("يبيب")
binding.tv.text = stringBuffer.toString().biDiFormat()

在系统语言是自左向右环境下显示如下
在这里插入图片描述

2. 示例二
var  msg = "<nickName> أرسل إلى <receiverNames> <giftIcon> <count>"

假设上述文本要在系统语言是自右向左下正确显示,那么它显示的结果应该是下面这样

var  msg = "<count> <giftIcon> <receiverNames> أرسل إلى <nickName>"

那要怎么样才能达到这个效果呢
首先我将msg整体进行一次bidiFormat

 var  msg = "<nickName> أرسل إلى <receiverNames> <giftIcon> <count>"
 binding.tv.text = msg.biDiFormat()

此时在自右向左下显示的结果如下:
在这里插入图片描述

通过上图发现,上述文本拆分成
<nickName>、<receiverNames> <giftIcon> <count>、أرسل إلى
三个部分,然后<nickName>和<receiverNames> <giftIcon> <count>做了一个整体的镜像,但是这并没有达到我们的效果。

下面我们把 <giftIcon> 这个做了一个biDiFormat

 var  msg = "<nickName> أرسل إلى <receiverNames> <giftIcon> <count>"
 msg = msg.replace("<giftIcon>","<giftIcon>".biDiFormat())
 binding.tv.text = msg.biDiFormat()

在这里插入图片描述

此时显示的结果就符合我们的预期了。
给<giftIcon>加上biDiFormat之后,
相当于给<giftIcon>整体包裹起来,然后它的顺序就变成是自右向左的模式,
所以它会把两端的文本格式是自左向右的进行互换位置。

3. 示例三
var  msg = "<nickName> أرسل إلى <receiverNames> <giftName> <giftIcon> <count>"

假设上述文本要在系统语言是自右向左下正确显示,那么它显示的结果应该是下面这样

var  msg = "<count> <giftIcon> <giftName> <receiverNames> أرسل إلى <nickName>"

那要怎么样才能达到这个效果呢
首先我将msg整体进行一次bidiFormat

 var  msg = "<nickName> أرسل إلى <receiverNames> <giftName> <giftIcon> <count>"
 binding.tv.text = msg.biDiFormat()

此时在自右向左下显示的结果如下:
在这里插入图片描述

通过上图发现,上述文本拆分成
<nickName>、<receiverNames> <giftName> <giftIcon> <count>、أرسل إلى
三个部分,然后<nickName>和<receiverNames> <giftName> <giftIcon> <count>做了一个整体的镜像,但是这并没有达到我们的效果。

下面我们把 <giftName> 这个做了一个biDiFormat

         var  msg = "<nickName> أرسل إلى <receiverNames> <giftName> <giftIcon> <count>"
        msg = msg.replace("<giftName>","<giftName>".biDiFormat())
        binding.tv.text = msg.biDiFormat()

在这里插入图片描述

位置互换的逻辑跟示例二一致,以<giftName>为中心,<receiverNames>、<giftIcon> <count> 进行位置互换。
此时还未符合我们的预期,<giftIcon> <count> 位置还需要进行调换,

下面我们把 <count> 这个做了一个biDiFormat

         var  msg = "<nickName> أرسل إلى <receiverNames> <giftName> <giftIcon> <count>"
        msg = msg.replace("<giftName>","<giftName>".biDiFormat())
        msg = msg.replace("<count>","<count>".biDiFormat())
        binding.tv.text = msg.biDiFormat()

在这里插入图片描述

因为<giftName>已经做过一次biDiFormat(),它就是自右向左所以它的位置不会变更。
那么最后<giftIcon>和<count>进行位置互换,此时显示的结果就符合我们的预期了。

4. 示例四
var  msg = "<nickName> <address> أرسل إلى <receiverNames> <giftName> <giftIcon> <count>"

假设上述文本要在系统语言是自右向左下正确显示,那么它显示的结果应该是下面这样

var  msg = "<count> <giftIcon> <giftName> <receiverNames> أرسل إلى <address> <nickName>"

那要怎么样才能达到这个效果呢
首先我将msg整体进行一次bidiFormat

 var  msg = "<nickName> <address> أرسل إلى <receiverNames> <giftName> <giftIcon> <count>"
 binding.tv.text = msg.biDiFormat()

此时在自右向左下显示的结果如下:
在这里插入图片描述

通过上图发现,上述文本拆分成
<nickName> <address>、<receiverNames> <giftName> <giftIcon> <count>、أرسل إلى
三个部分,然后<nickName> <address>和<receiverNames> <giftName> <giftIcon> <count>做了一个整体的镜像,但是这并没有达到我们的效果。

下面我们把 <giftIcon> 这个做了一个biDiFormat

         var  msg = "<nickName> <address> أرسل إلى <receiverNames> <giftName> <giftIcon> <count>"
        msg = msg.replace("<giftName>","<giftName>".biDiFormat())
         msg = msg.replace("<count>","<count>".biDiFormat())
        msg = msg.replace("<address>","<address>".biDiFormat())
        binding.tv.text = msg.biDiFormat()

在这里插入图片描述

此时显示的结果就符合我们的预期了。

上述如有理解不对的地方,欢迎大家一起探讨。

2.关于实现上面功能中途碰到另外两个小问题
  • 1.当文本中存在两个连续空格的情况下,经过Html.fromHtml后空格只显示一个,
    所以我们需要通过replace(" ", "\u00A0")进行替换。

  • 2.关于Spanned当中几个标志位
    SPAN_EXCLUSIVE_EXCLUSIVE 不包含两端
    SPAN_INCLUSIVE_INCLUSIVE 包含两端
    SPAN_EXCLUSIVE_INCLUSIVE 不包含开始 包含结尾
    SPAN_INCLUSIVE_EXCLUSIVE 包含开始 不包含结尾

具体的理解以及示例大家可以去这里看

好了,全文结束,如有问题,欢迎大家指正交流~
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值