1. 程式人生 > >Android 本地化適配:RTL(right-to-left) 適配清單

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


公眾號後臺回覆成長『成長』,將會得到精心準備的學習資料。

相關推薦

Android 本地化RTLright-to-left 清單

本文首發自公眾號:承香墨影(ID:cxmyDev),歡迎關注。 一. 序 越來越多的公司 App,都開始淘金海外,尋找更多的機會。然而海外市場千差萬別,無論是市場還是使用者的使用習慣,都有諸多的不同。 當你接觸一款出海 App 的時候,除了需要了解海外 Google Service 的整個生態圈,還要做好

Android 自用 App保活——音樂播放保活8.0 賊好用

又是好久沒有積累東西了。慚愧,慚愧。。。手動哭泣。閒話說到這裡,下面我介紹一種新的 App 保活方式哈,目前用小米家族手機 涵蓋 Android 5.0 到 Android 8.1家族的測試。結論是,不主動幹掉,是死不了的。但是主動幹掉了,是活不了的。 之前介紹介紹了 雙程序保活,我

Android項目實戰三十九Android集成Unity3D項目圖文詳解

jar包沖突 scree pmap module 項目實戰 技術 詳細 應用端 原來 原文:Android項目實戰(三十九):Android集成Unity3D項目(圖文詳解)  需求:   Unity3D 一般用於做遊戲 而且是跨平臺的。原本設計是Android 應用端A

Android Api Demos登頂之路四十五Loader--&gt;Cursor

adapt lists 清空 function icon 創建 nal pat lines 這個demo演示了類載入器的用法。關於類載入器的使用我們在前面的demo中已經介紹過了 在此再小小的復習一下。類載入器的使用步驟: * 1.獲取類載入

Android動畫效果之Frame Animation逐幀動畫

想要 顯示 star 載體 rop 復雜 ide sources post 前言: 上一篇介紹了Android的Tween Animation(補間動畫) Android動畫效果之Tween Animation(補間動畫),今天來總結下Android的另外一種動

BZOJ 1626 [Usaco2007 Dec]Building Roads 修建道路kruskal最小生成樹

push_back spa pri family sca iostream 長度 con end 題目鏈接:http://www.lydsy.com/JudgeOnline/problem.php?id=1626 題意:   有n個農場,坐標為(x[i],y[i])。   

Android------Button 添加聲音效果兩種方式

div abs 一次 播放 pool 當前 傳送門 ide col 我在先前的案例《Android 的底部導航欄 BottomNavigationBar》中添加以底部 的4個按鈕切換添加聲音 下來看看案例效果圖 使用添加依賴 comp

筆記RMQ區間最值之ST算法

運算 不變 想要 parse 計算機語言 c++ 是我 動態規劃 容易 RMQ(區間最值)之ST算法 RMQ即Range Minimum/Maximun Query 中文意思:查詢一個區間的最小值/最大值 比如有這樣一個數組:A{3 2 4 5 6 8 1 2 9 7},

BZOJ1854遊戲二分圖匹配

find als 數值 每次 輸入 algo names sin str lxhgww最近迷上了一款遊戲,在遊戲裏,他擁有很多的裝備,每種裝備都有2個屬性,這些屬性的值用[1,10000]之間的數表示。當他使用某種裝備時,他只能使用該裝備的某一個屬性。並且每種裝備最多只能使

Android Studio生成簽名安裝包Generate Signed APK

打開 對話 store microsoft oid 選擇 安裝 height androi 一 打開構建對話框。 二 創建新的密鑰庫(key store) 可以選擇已創建的密鑰庫,也可以選擇創建新的密鑰庫。 創建完成後,自動導入。

Android 運行時權限危險權限

一個 IE ID 通訊錄 rac provider param HR extend 一、說明 Android 6.0開始,Google將權限分為兩類,一類是Normal Permission, 這類權限一般不涉及用戶隱私,是不需要用戶進行授權的,比如手機震動、訪問網絡等;另

UVA297Quadtrees四分樹

sam 數組 while 規則 bool put http truct mage 題目描述 四象樹是每個內結點均有4個子結點的特殊四叉樹,它可用於描述平面上黑白圖像。平面上的黑白圖像是32行×32列的正方形,每個格子稱為1個象素,是最小的圖像單位。正方形圖像可分成四個相等

java.lang下面有一個接口Comparable可比較的

一個 情況下 span UNC lis fat 只有一個 比較 ati 對於自定義對象,Sort不知道規則,所以無法比較。這種情況下一定要定義排序規則。方式有兩種: java.lang下面有一個接口:Comparable(可比較的) 可以讓自定義對象實現一個接口,這個接口只

雜項-QXMCFA特許金融分析師

ech 頁面 mage strong spa ike ack 否則 clas ylbtech-雜項-QXM:CFA(特許金融分析師) 1.返回頂部 1、 CFA是“特許金融分析師”(Chartered Financial Analyst)的簡

jchdl - GSL實例FullAdder使用HalfAdder實現

二進制 實例 ttr tencent 技術 dom logic master ast https://mp.weixin.qq.com/s/5mcYAllizuxyr3QSNrotrw 全加器是能夠計算低位進位的二進制加法電路。與半加器相比,全加器不只考慮本位計算結果

ELK系列安裝elasticsearch + logstash + kibana

minimum 5.6 解壓 通過 stdout you targe 記錄 pat 因為公司使用ELK的緣故,這兩天嘗試在阿裏雲上安裝了下ELK,這裏做個筆記,有興趣的同學可以看下。 先大致介紹下ELK,ELK是三個組件的縮寫,分別是elasticsearch、logsta

HDU - 5936 Difference中途相遇法

lock ret members www positive from bug return and Little Ruins is playing a number game, first he chooses two positive integers yy and KK

Android全局可調試ro.debuggable = 1的一種另類改法

cal size kill -9 detach root img 地址 poke service 網上流傳比較多的,是重打包boot.img。讀aosp的init進程源碼,發現通過patch init進程也可以實現相同目的。 首先看一下init進程對ro只讀屬性的檢查: /

android UVC h264 ffmpeg硬解碼RK3288 android5.1

username需求:由於軟解碼速度跟不上導致解碼花屏嚴重,轉用ffmpeg交叉編譯android 5.1原始碼硬解碼。   假設已經編譯好RK3288 android5.1系統(主要是硬編碼用到的libstagefright庫) 系統編譯參考:https://blog.csd

HDU1083 Courses二分圖匹配

ostream 鏈接 ise ide sat mit ask first repr Cources Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To