zoukankan      html  css  js  c++  java
  • Android 本地化适配:RTL(right-to-left) 适配清单

    本文首发自公众号:承香墨影(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 布局为镜像后的效果。

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

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

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

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

    到这里应该了解了,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 的自动调整。

    它会自动将项目中所有的 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 的适配。例如在不同方向的布局下,使用不同的图标。

    上图就是个很典型的例子,在调整布局到 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/usability/bidirectionality.html#localization),设计师可以参考。

    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-gomez-olvera/RtlViewPager) 可供使用。其原理也是将数据进行倒序重排,没什么好说的,源码不多,有兴趣可以自己看看。

    四. 适配 RTL 要如何估期?

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

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

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

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

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

    1. 设置 android:supportsRtl="true",让 App 支持 RTL。
    2. AS 自动转换布局属性,支持 RTL 布局效果。
    3. 打开开发者选项中的「强制使用从右到左的布局方向」,强制 RTL 布局。

    此时你基本上可以看到一个 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/usability/bidirectionality.html#localization

    https://android-developers.googleblog.com/2013/03/native-rtl-support-in-android-42.html

    https://developer.android.com/training/basics/supporting-devices/languages?hl=zh-cn


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

  • 相关阅读:
    android81 多线程下载和断电续传
    android80 HttpClient框架提交数据 get方式
    CentOS 7最小化安装后找不到‘ifconfig’命令——修复小提示
    Eclipse4.5在线安装Aptana插件及配置代码提示教程
    centos7 yum源
    ESXi License过期解决办法
    mysql grant 用户权限总结
    Unable to locate package错误解决办法
    华为USG6350防洪墙SNMP最简单功能配置
    ssl_error_weak_server_ephemeral_dh_key
  • 原文地址:https://www.cnblogs.com/plokmju/p/android_rtl.html
Copyright © 2011-2022 走看看