33

Android 本地化适配:RTL(right-to-left) 适配清单

 4 years ago
source link: https://www.tuicool.com/articles/Vru67vf
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

fQb2MnF.png!web

本文首发自公众号:承香墨影(ID:cxmyDev),欢迎关注。

一. 序

越来越多的公司 App,都开始淘金海外,寻找更多的机会。然而海外市场千差万别,无论是市场还是用户的使用习惯,都有诸多的不同。

当你接触一款出海 App 的时候,除了需要了解海外 Google Service 的整个生态圈,还要做好不同语言的适配。语言适配最通用的做法就是根据不同系统语言设定,配置不同的语言资源(strings.xml),而其中比较特殊的就是例如阿拉伯的 RTL 布局,它不仅改变了语言,还改变了 UI 布局和使用习惯。

我们常用的习惯,称之为 LTR(Left-To-Right),其意为我们的阅读和书写习惯,是从左向右延伸的。而 RTL(Right-To-Left) 则正好相反,它的阅读和使用的习惯都是从右向左,常见使用 RTL 习惯的语言有阿拉伯语、希伯来语等。

今天就来聊聊,一个成熟的 Android App,想要做 RTL 适配,需要关注什么,想要适配 RTL 有哪些任务清单。

如果你维护的 App 有国际化的要求,那这个问题是迟早需要面对的。

二. Android 支持 RTL

2.1 什么是 RTL?

正如前面介绍的,RTL 是 Right-to-left 的缩写,其意为阅读和书写的习惯,是从右向左延伸的。再对比一下我国人自身的使用习惯,都是 LTR 的,也就是从左向右。

RTL 可以简单理解是 LTR 的镜像,当需要适配 RTL 的时候,除了翻译语言本身,还需要做到的就是 UI 布局,从中轴上镜像反转。

虽然 RTL 不符合我们国人的使用习惯,但是全球范围内依然有一部分人保持着 RTL 的习惯,比较常见的就是阿拉伯语、希伯来语等。

就 Android 系统来说,Android 4.1 开始就在 TextView 和 EditView 中增加了对双向文本的优先支持,允许其文本内容从左向右(LTR)到从右向左(RTL)的显示和切换。而在 Android 4.2 开始,增加了对 RTL 镜像布局完全原生的支持。

也就是在 Android 4.2(Api Level 17)及之后,在 UI 上的布局镜像,是原生支持的。在这些系统版本上,只要用户系统语言切换到「RTL 系语言」,首先系统 UI 会直接左右镜像切换,此时如果你的 App 支持 RTL 镜像布局时,也会自动切换布局方向。

2.2 App 如何支持 RTL 镜像

正如前面介绍的一样,LTR 到 RTL 的切换,不是由开发者控制的,而通常是由系统语言来控制的。

当系统语言切换为「RTL 系语言」时,还需要你的 App 支持 RTL 镜像布局。

这里所谓的支持,其实只需要配置一个属性即可,就是 AndroidManifest.xml 配置文件中的一个清单元素。需要在 <applictaion> 标签下,配置元素 android:supportsRtl="true"

此时当系统语言切换的时候,你的 App 也会跟着切换 UI 布局为镜像后的效果。

V3I3AnN.png!web

除了需要开启 supportsRtl 属性之外,还需要一些布局属性的配合。

简单来说,就是将布局需要的所有 xxxLeft/xxxRight "替换"为 xxxStart/xxxEnd。

例如我们常用的 Padding 和 Margin,都有类似 paddingLeft 和 layout_marginRight 属性,这些就需要"替换"成 paddingStart 和 layout_marginEnd 属性。当然不止于此,还有一些 gravity、drawableLeft 等属性需要"替换"。原则上,所有 Left/Right 都需要变换为 Start/End 就好了。

这些属性,官方文档中已经帮我们列举出来了。

myimUfJ.png!web

到这里应该了解了,Android App 支持 RTL 镜像的主要流程,就两步:

  1. App 增加 android:supports="true" 属性。
  2. 调整 UI 布局属性,从 left/rightstart/end 切换。

那么问题来了,我们在日常编码的过程中,应该使用 left/right 还是 start/end?还是两者都需要?

注意到我前面提到的 UI 布局属性的替换时,是打了引号的,你是否需要使用 start/end 来完全替换 left/right ,完全取决于 App 当前的 minSdkVersion 值。

正如前面所提到的,Android 对 RTL 的原生支持,是在 Android 4.2 中才具备的,也就是说,如果 App 的 minSdkVersion 大于等于 4.2,你只需要使用 start/end 属性,但如果还需要支持 4.2 以下的设备用户,那就需要保留 left/rightstart/end 两者。

在低于 4.2 的系统中,不识别 supportsRtlstart/end 属性,所以不会造成影响。但是需要注意,在适配完成之后,后续开发新页面时的编码习惯。

2.3 AS 助力调整布局属性

如果当前需要适配的是一个成熟项目,并且其中的布局习惯还是使用 left/right 系的属性,那么针对所有页面布局文件,进行手工调整就是一个非常大的工作量了。

所幸的是 AS 提供了自动化的支持。

你可以在 Refactor → Add RTL Support Where Possible 来开启 RTL 的自动调整。

JrMziu7.png!web

它会自动将项目中所有的 left/right 属性都替换为 start/end 属性,如果想要适配 Android 4.2 以下的设备,需要保留两者,那么在 Run 之前,勾选 Relpace Left/Right Properties with Start/End Properties 选项即可。

早期的 AS 自动支持 RTL 布局的时候,效率会有一些问题,转换的时候如果布局过多,可能会卡死,但是新版的 AS 已经优化了很多,转换效率上还是可以接受的。

另外这毕竟是自动替换,在替换完成之后,还是需要每个页面都测试一遍,看看效果才算完,有时候还需要我们做一些微调的工作。例如 AS 自动替换 RTL 布局的时候,如果使用了 include 标签,其中用到的方向属性不会被替换。

自动化虽然方便了我们机械的重复,但也必须介入人工的干预符合预期。

三. RTL 细节调整

要做这种全全局的改动,必然会有一些细节需要微调的,这里简单写一些 RTL 布局中会需要使用到的细节调整技巧。

3.1 利用全局样式,批量修改属性

在适配 RTL 的过程中,无法避免的就是有一些属性必须要设置。例如 EditView 就需要设置以下属性。

android:textAlignment="viewStart"
android:gravity="start"
android:textDirection="locale"

那我们就可以将这些属性在 style.xml 中全局为 EditText 设置上。

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
       ...
       <item name="editTextStyle">@style/EditTextStyle.Alignment</item>
       ...
</style>

<style name="EditTextStyle.Alignment" parent="@android:style/Widget.EditText">
        <item name="android:textAlignment">viewStart</item>
        <item name="android:gravity">start</item>
        <item name="android:textDirection">locale</item>
</style>

同时 TextView 也需要设置 android:textDirection 属性,也可以采用相同的方法用 Style 的方式全局设置。

3.2 针对 RTL 的资源适配

除了布局上的适配之外,还有一些资源的适配,资源适配主要说两块内容:Drawable(mipmap) 以及 Layout 布局资源。

先来说说 Drawable 的适配。例如在不同方向的布局下,使用不同的图标。

UZzuUrb.png!web

上图就是个很典型的例子,在调整布局到 RTL 时,还需要注意返回「 」的图标也需要替换成「 」。

这里依然使用 Android 对资源使用的限定符的方式,可以创建 drawable-ldrtl 目录,将翻转后的图标,放在这个目录下。如果需要限定 dpi,可以在目录名后面追加。

res/
  drawable/
    a.png  
  drawable-ldrtl/
    a.png  // 对标 drawable/a.png 的 RTL 图标
  drawable-xhdpi/
    b.png  
  drawable-ldrtl-xhdpi/
    b.png  // 对标 drawable-xhdpi/b.png 的 RTL 图标

接下来再说说 Layout 布局的 RTL 布局效果适配。有些特殊的页面,可能光镜像化还不够,还需要针对性的做一些 UI 上的调整,那最简单的做法就是做两套布局,互不影响。

既然 Drawable 可以通过资源限定符的方式,设置 RTL 布局下使用的图标,其实布局也可以。

对于布局文件,可以在目录下追加限定符 layout-ldrtl/ ,如果想对某个语言做布局适配,也可以增加语言限定,例如阿拉伯语可以用 layout-ar/

res/
  layout/
    main.xml  // 默认布局
  layout-ar/
    main.xml  // 阿拉伯语布局
  layout-ldrtl/
    main.xml  // RTL 布局

针对 RTL 的 UI 布局规范,Material Design 下有一个规范的文档( https://material.io/design/us... ),设计师可以参考。

3.3 代码判断是否 RTL?

有些控件的属性,是通过代码动态调整的,那在使用的过程中,就需要在代码中,判断当前的环境,是 RTL 还是 LTF,才可以确定后续的属性设置。

通过获取 Configuration 的 locale 来判断当前的环境,为了兼容,在 TextUtilsCompat 下也提供了类似的方法。

public boolean isRtl() {
    return TextUtilsCompat.getLayoutDirectionFromLocale(
        getContext().getResources().getConfiguration().locale) ==         ViewCompat.LAYOUT_DIRECTION_RTL;
}

isRtl() 方法可以直接拿来使用,依此判断结果,执行后续的操作。

3.4 不是所有控件都支持 RTL

虽说从 Android 4.2 开始,原生支持 RTL 方向布局,但是也有一些控件是不支持的,例如 ViewPager,就不支持 RTL 的方向。

这其实没有什么很好的办法,要么和产品商量对此处的容忍,要么找一些其他的解决方案。

针对 ViewPager 的 RTL 化,在 Github 就有对应的开源库 RtlViewPager( https://github.com/diego-gome... ) 可供使用。其原理也是将数据进行倒序重排,没什么好说的,源码不多,有兴趣可以自己看看。

四. 适配 RTL 要如何估期?

再来聊聊适配 RTL 时,估算开发周期的问题。

除了 App 本身在设计研发之初,就是为了中东的土豪设计的之外,多数情况下,我们都是因为各种外部原因,需要在一款成熟的 App 上,适配 RTL 镜像布局。例如市场验证有大量「RTL 系语言」的付费用户,或者产品经理认为存在「RTL 系语言」的潜在用户。

什么时候适配 RTL,完全是由外部因素决定的。但是当需要适配的时候,我们作为开发者,最直观要面对的现实问题就是,适配 RTL 需要做哪些事?这个任务需要多少时间能够完成?需要哪些人来配合,哪些任务是可以并行的?

要精确估计 App 的 RTL 化,很难,因为工作量主要来自适配,说到适配,工作量就可大可小了。App 大量使用第三方控件的就比只使用原生控件的工作量大;产品经理和设计师,允许部分页面适配有差异的,也会比高要求还原的工作量大。

这些在适配完成之前,谁也不知道效果如何,既然没有什么好的方法,那就试一试吧,只需要三步,你可以拿着一个明确的镜面翻转效果,来估计适配的难度。

android:supportsRtl="true"

6VFF73Y.png!web

此时你基本上可以看到一个 80% RTL 化的 App,剩下的就是把页面都检查一遍,看看有没有用到哪些控件不支持 RTL,哪些 Drawable 需要替换、哪些布局需要微调。然后针对性的调整即可。

有一些控件不支持 RTL 就会比较麻烦,有源码的就改改源码,没源码的就看有没有地方可以 Hook 解决。

总之需要做什么,清单是固定的。有了明确的任务,自然就容易估计开发周期了。

列举一下适配 RTL 的任务清单:

  1. App 支持 RTL,AS 自动转换布局属性支持 RTL,从开发者选项里强制 RTL 布局方向。
  2. 按页面排查,检查出需要翻转的 Drawable 资源,打包交给设计师,反转后替换。
  3. 检查布局翻转后的效果,和设计师确定需要适配翻转后的 UI 效果。
  4. 找到不支持 RTL 化的控件,可以从源码的角度分析,能改源码的改源码,不能改源码的尝试 Hook 解决或找替代方案。
  5. 翻译 RTL 系语言资源 strings.xml,放入对应的资源目录,例如阿拉伯语需要放入 /values-ar/strings.xml 目录,将系统语言切换到阿拉伯语,排查所有页面文字与控件的匹配度。
  6. 整体验收,微调效果。

其中需要和产品、设计、翻译配合的,都可以提前准备,让任务并行化。当然在适配的过程中,还有一些实际的问题,就需要遇到问题再解决问题了。

五. 小结时刻

本文聊了如何在一个成熟的 App 上,适配 RTL 镜像效果,以及如何快速的适配。最后还列出了一个适配时,需要调整关注的清单列表,希望对你有所帮助。

本文就到这里,如果有所帮助, 留言、转发、点好看 是最大的支持,谢谢!

reference:

https://material.io/design/us...

https://android-developers.go...

https://developer.android.com...

公众号后台回复成长『 成长 』,将会得到精心准备的学习资料。

2qMFn2j.png!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK