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 镜像的主要流程,就两步:
- 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 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 大量使用第三方控件的就比只使用原生控件的工作量大;产品经理和设计师,允许部分页面适配有差异的,也会比高要求还原的工作量大。
这些在适配完成之前,谁也不知道效果如何,既然没有什么好的方法,那就试一试吧,只需要三步,你可以拿着一个明确的镜面翻转效果,来估计适配的难度。
- 设置
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 镜像效果,以及如何快速的适配。最后还列出了一个适配时,需要调整关注的清单列表,希望对你有所帮助。
本文就到这里,如果有所帮助,留言、转发、点好看是最大的支持,谢谢!
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
公众号后台回复成长『成长』,将会得到精心准备的学习资料。
Android 本地化适配:RTL(right-to-left) 适配清单的更多相关文章
- Android 8.0系统的应用图标适配
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 参考资料<一起来学习Android 8.0系统的应用图标适配吧>中已经讲得很清楚了,这里我只是简单总结下.详情的内容请阅 ...
- Android屏幕适配框架-(今日头条终极适配方案)
在Android开发中,屏幕适配是一个非常头痛的问题,因而为了去进行屏幕适配,作为程序员,是呕心沥血,历经磨难,哈哈 我们之前做屏幕适配一般都会用到一下两种方式: 第一种就是宽高限定符适配,什么是宽高 ...
- Android app 在线更新那点事儿(适配Android6.0、7.0、8.0)
一.前言 app在线更新是一个比较常见需求,新版本发布时,用户进入我们的app,就会弹出更新提示框,第一时间更新新版本app.在线更新分为以下几个步骤: 1, 通过接口获取线上版本号,versionC ...
- Android WiFi热点7.1以上版本适配
代码地址如下:http://www.demodashi.com/demo/13907.html 一.准备工作 开发环境: jdk1.8 AS(3.0.1) 运行环境: 华为V10(Android ...
- Android开发 MediaPlayer将视频播放时尺寸适配完美
前言 视频播放有一个较为蛋疼的问题,那就是尺寸适配.如果不做尺寸适配视频将会变形拉伸或者压缩.下面我就介绍个人实现的算法. 满足一边的算法 满足一边?你可能是疑问是什么意思.意思是就是始终将视频的高度 ...
- iOS:界面适配(三)--iPhone不同机型适配 6/6plus 前
转:http://blog.csdn.net/houseq/article/details/40051207 对于不同苹果设备,各个参数查看<iOS:机型参数.sdk.xcode各版本>. ...
- android多分辨率多屏幕密度下UI适配方案
相关概念 分辨率:整个屏幕的像素数目,为了表示方便一般用屏幕的像素宽度(水平像素数目)乘以像素高度表示,形如1280x720,反之分辨率为1280x720的屏幕,像素宽度不一定为1280 屏幕密度:表 ...
- android 屏幕适配1 ——dimens.xml的适配
1.如果是才开始做项目,已经有设计图:720*1280 1).默认values文件夹:1dp=1px values/dimens_x.xml: name: x1~x720 value:1px~72 ...
- Android实战开发租赁管理软件(适配UI,数据的存储,多线程下载)课程分享
亲爱的网友,我这里有套课程想和大家分享,假设对这个课程有兴趣的,能够加我的QQ2059055336和我联系. 课程内容简单介绍 我们软件是基于移动设备的.所以我们必定的选择了安卓作为我们的开发工具.课 ...
随机推荐
- 二.安全NA之ASA基础
一.ASA常用命令 show run interface #查看接口配置 show ip address #查看IP地址 show conn #查看防火墙状态信息,U代表up:I,代表进流量:O,代表 ...
- Nacos(二):SpringCloud项目中接入Nacos作为注册中心
前言 通过上一篇文章:Nacos介绍简单了解了Nacos的发展历程和现状,本文我们开始Nacos试水的第一步: 使用Nacos做注册中心 上周末(7.6)Nacos发布了V1.1.0版本,这次更新支持 ...
- Spring-boot:多模块打包
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot ...
- 常用加密解密算法【RSA、AES、DES、MD5】介绍和使用
内容不转载了,加上链接https://blog.csdn.net/u013565368/article/details/53081195?_t=t
- css_transition_animation(内含贝赛尔曲线详解)
区别: transition也叫过渡动画,主要是用于让一个元素从一种状态过渡到另一种状态效果,常用于主动触发的效果.例如移动端的页面切换(很常用).button点击效果(也很常见). animatio ...
- 杭电多校 hdu6627 equation
http://acm.hdu.edu.cn/showproblem.php?pid=6627 题意:解绝对值方程并统计解的个数. 解法:签到题,直接模拟小学数学学的零点分段法即可.(数据多直接cin, ...
- poj 2253 Frogger(floyd变形)
题目链接:http://poj.org/problem?id=1797 题意:给出两只青蛙的坐标A.B,和其他的n-2个坐标,任一两个坐标点间都是双向连通的.显然从A到B存在至少一条的通路,每一条通路 ...
- 用户上传gif动图分解成多张帧图片,并合并生成新gif图片
背景 为什么要制作这么一款工具 首先公司最近在做一款表情包的产品,需要将文字生成到gif图片中,并可以控制文字显示的位置,并将不同的文字显示在不同的图片上 制作成网页端工具,随时随地,方便使用 探索 ...
- Java Web第一个应用搭建
导语:搭建一个JAVA WEB,首先你要安装好java,如果不知道怎么安装Java的同学,可以自行百度,这里不做讲解.安装好java之后,我们还需要安装一个本地服务器,这里我们用到的是Tomcat.接 ...
- 章节十六、8-ITestResult接口
一.ITestResult:该接口就像一个监听器,能够监听每个方法执行后的状态(是否成功)并将结果返回给我们. package testclasses1; import org.testng.anno ...