本文首发自公众号:承香墨影(ID:cxmyDev),欢迎关注。html
愈来愈多的公司 App,都开始淘金海外,寻找更多的机会。然而海外市场千差万别,不管是市场仍是用户的使用习惯,都有诸多的不一样。java
当你接触一款出海 App 的时候,除了须要了解海外 Google Service 的整个生态圈,还要作好不一样语言的适配。语言适配最通用的作法就是根据不一样系统语言设定,配置不一样的语言资源(strings.xml),而其中比较特殊的就是例如阿拉伯的 RTL 布局,它不只改变了语言,还改变了 UI 布局和使用习惯。android
咱们经常使用的习惯,称之为 LTR(Left-To-Right),其意为咱们的阅读和书写习惯,是从左向右延伸的。而 RTL(Right-To-Left) 则正好相反,它的阅读和使用的习惯都是从右向左,常见使用 RTL 习惯的语言有阿拉伯语、希伯来语等。git
今天就来聊聊,一个成熟的 Android App,想要作 RTL 适配,须要关注什么,想要适配 RTL 有哪些任务清单。github
若是你维护的 App 有国际化的要求,那这个问题是早晚须要面对的。app
正如前面介绍的,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 镜像布局时,也会自动切换布局方向。
正如前面介绍的同样,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 镜像的主要流程,就两步:
android:supports="true"
属性。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
属性,因此不会形成影响。可是须要注意,在适配完成以后,后续开发新页面时的编码习惯。
若是当前须要适配的是一个成熟项目,而且其中的布局习惯仍是使用 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 的过程当中,没法避免的就是有一些属性必需要设置。例如 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 的方式全局设置。
除了布局上的适配以外,还有一些资源的适配,资源适配主要说两块内容: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/us...),设计师能够参考。
有些控件的属性,是经过代码动态调整的,那在使用的过程当中,就须要在代码中,判断当前的环境,是 RTL 仍是 LTF,才能够肯定后续的属性设置。
经过获取 Configuration 的 locale 来判断当前的环境,为了兼容,在 TextUtilsCompat 下也提供了相似的方法。
public boolean isRtl() { return TextUtilsCompat.getLayoutDirectionFromLocale( getContext().getResources().getConfiguration().locale) == ViewCompat.LAYOUT_DIRECTION_RTL; }
isRtl()
方法能够直接拿来使用,依此判断结果,执行后续的操做。
虽然说从 Android 4.2 开始,原生支持 RTL 方向布局,可是也有一些控件是不支持的,例如 ViewPager,就不支持 RTL 的方向。
这其实没有什么很好的办法,要么和产品商量对此处的容忍,要么找一些其余的解决方案。
针对 ViewPager 的 RTL 化,在 Github 就有对应的开源库 RtlViewPager(https://github.com/diego-gome...) 可供使用。其原理也是将数据进行倒序重排,没什么好说的,源码很少,有兴趣能够本身看看。
再来聊聊适配 RTL 时,估算开发周期的问题。
除了 App 自己在设计研发之初,就是为了中东的土豪设计的以外,多数状况下,咱们都是由于各类外部缘由,须要在一款成熟的 App 上,适配 RTL 镜像布局。例如市场验证有大量「RTL 系语言」的付费用户,或者产品经理认为存在「RTL 系语言」的潜在用户。
何时适配 RTL,彻底是由外部因素决定的。可是当须要适配的时候,咱们做为开发者,最直观要面对的现实问题就是,适配 RTL 须要作哪些事?这个任务须要多少时间可以完成?须要哪些人来配合,哪些任务是能够并行的?
要精确估计 App 的 RTL 化,很难,由于工做量主要来自适配,说到适配,工做量就可大可小了。App 大量使用第三方控件的就比只使用原生控件的工做量大;产品经理和设计师,容许部分页面适配有差别的,也会比高要求还原的工做量大。
这些在适配完成以前,谁也不知道效果如何,既然没有什么好的方法,那就试一试吧,只须要三步,你能够拿着一个明确的镜面翻转效果,来估计适配的难度。
android:supportsRtl="true"
,让 App 支持 RTL。此时你基本上能够看到一个 80% RTL 化的 App,剩下的就是把页面都检查一遍,看看有没有用到哪些控件不支持 RTL,哪些 Drawable 须要替换、哪些布局须要微调。而后针对性的调整便可。
有一些控件不支持 RTL 就会比较麻烦,有源码的就改改源码,没源码的就看有没有地方能够 Hook 解决。
总之须要作什么,清单是固定的。有了明确的任务,天然就容易估计开发周期了。
列举一下适配 RTL 的任务清单:
其中须要和产品、设计、翻译配合的,均可以提早准备,让任务并行化。固然在适配的过程当中,还有一些实际的问题,就须要遇到问题再解决问题了。
本文聊了如何在一个成熟的 App 上,适配 RTL 镜像效果,以及如何快速的适配。最后还列出了一个适配时,须要调整关注的清单列表,但愿对你有所帮助。
本文就到这里,若是有所帮助,留言、转发、点好看是最大的支持,谢谢!
reference:
https://material.io/design/us...
https://android-developers.go...
https://developer.android.com...
公众号后台回复成长『 成长』,将会获得精心准备的学习资料。