Android RTL适配:需要做哪些工作

Android RTL适配:需要做哪些工作呢?

一. 序

越来越多的公司 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 镜像的主要流程,就两步:

App 增加 android:supports="true" 属性。

调整 UI 布局属性,从 left/right 到 start/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/right 和 start/end 两者。

在低于 4.2 的系统中,不识别 supportsRtl 和 start/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/EditTextStyle.Alignment...viewStartstartlocale

同时 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 下也提供了类似的方法。

publicbooleanisRtl(){returnTextUtilsCompat.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 大量使用第三方控件的就比只使用原生控件的工作量大;产品经理和设计师,允许部分页面适配有差异的,也会比高要求还原的工作量大。

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

设置 android:supportsRtl="true",让 App 支持 RTL。

AS 自动转换布局属性,支持 RTL 布局效果。

打开开发者选项中的「强制使用从右到左的布局方向」,强制 RTL 布局。

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

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

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

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

App 支持 RTL,AS 自动转换布局属性支持 RTL,从开发者选项里强制 RTL 布局方向。

按页面排查,检查出需要翻转的 Drawable 资源,打包交给设计师,反转后替换。

检查布局翻转后的效果,和设计师确定需要适配翻转后的 UI 效果。

找到不支持 RTL 化的控件,可以从源码的角度分析,能改源码的改源码,不能改源码的尝试 Hook 解决或找替代方案。

翻译 RTL 系语言资源 strings.xml,放入对应的资源目录,例如阿拉伯语需要放入 /values-ar/strings.xml 目录,将系统语言切换到阿拉伯语,排查所有页面文字与控件的匹配度。

整体验收,微调效果。

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

五. 小结时刻

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

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

转自:https://www.cnblogs.com/plokmju/p/android_rtl.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • 概述 阿拉伯作为一个土豪帝国,android在sdk17(Android4.2)也开始支持RTL(right to...
    Android深夜食堂阅读 9,203评论 9 7
  • 本文为本人原创,转载请注明作者和出处。 因为业务原因,产品需要适配阿拉伯语语、波斯语、乌尔都语。而这三种语言都是从...
    业松阅读 6,872评论 0 5
  • 背景 阿拉伯语适配是一个比较麻烦的事情,不止在于它文案的适配,更多的是在于其语言习惯的变化。由从左到右(LeftT...
    小笨狼阅读 14,092评论 23 40
  • 该文章已归纳在本人 GitHub 的 Blog 仓库,欢迎 star 或者 watch。同时欢迎访问我的博客地址 ...
    GoJun阅读 30,383评论 6 34
  • APP国际化,说的直白应该也叫本土化或者本地化,如果你的应用上线到谷歌应用市场,那么应该做好本地化的支持,用来支持...
    Find_A_Way阅读 1,482评论 0 2