本文首發自公衆號:承香墨影(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 有國際化的要求,那這個問題是早晚須要面對的。bash
正如前面介紹的,RTL 是 Right-to-left 的縮寫,其意爲閱讀和書寫的習慣,是從右向左延伸的。再對比一下我國人自身的使用習慣,都是 LTR 的,也就是從左向右。app
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 下有一個規範的文檔(material.io/design/usab…
有些控件的屬性,是經過代碼動態調整的,那在使用的過程當中,就須要在代碼中,判斷當前的環境,是 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(github.com/diego-gomez… 可供使用。其原理也是將數據進行倒序重排,沒什麼好說的,源碼很少,有興趣能夠本身看看。
再來聊聊適配 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:
android-developers.googleblog.com/2013/03/nat…
developer.android.com/training/ba…
公衆號後臺回覆成長『成長』,將會獲得精心準備的學習資料。