標籤:android style class blog code java
前言
我們在使用Android手機系統的時候經常在“設定”項裡面會提供使用者多種系統語言選擇,比如:中文、英語…… 大家或許已經發現這些語言顯示順序都是“從左往右”;但是有一些語言是“從右往左”顯示的,比如阿拉伯語、希伯來語等語言,當在這種語言環境下時,我們需要怎麼來處理布局檔案呢?接下來的時間我們就來討論處理阿拉伯語等“從右往左”顯示語言的問題。
布局
首先我們先講解布局問題,在Android系統中為了支援不同語言顯示,可以定義特定(阿拉伯語、希伯來語……)語言布局檔案,具體:
圖中layout-ar對應的就是阿拉伯語的布局檔案,因此我們只需要修改該目錄下的布局檔案,就可以實現我們在阿拉伯語言環境中的現實效果。在Android4.2之前,我們需要對每一種“從右往左”顯示的語言copy一份布局檔案進行修改,中layout-fa layout-iw等,這樣做的缺點就是會產生許多冗餘布局檔案。
Android4.2版本之後,Google針對阿拉伯等bidi語言(備忘:bidi語言即“從右往左”書寫的語言)view和文字布局檔案做了重大修改,類似2D圖形加速機制,可以從Activity/Application控制、Window代碼控制、View資源控制共3個層級的控制。所有關於bidi語言的布局檔案都可以放在layout-ldrtl目錄,:
layout-ldrtl是Google專門為bidi語言預留的布局目錄,所以在Android4.2版本之後,layout-fa layout-iw等目錄可以直接刪除,只需要在layout-ldrtl目錄下定義bidi語言布局即可。
Activity/Application控制
在Manifest檔案中我們可以設定android:supportsRtl屬性,具體請參考如下代碼:
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:supportsRtl="true" >
View控制
在layout-ldrtl目錄的布局檔案中設定android:layoutDirection屬性,具體請參考如下代碼:
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:layoutDirection="rtl" > <TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/hello_world"android:layoutDirection="rtl" /></LinearLayout>
備忘:layout-ldrtl優先順序介紹,layout-ldrtl優先順序要低於語言層級(layout-ar),因此如果存在layout-ar目錄,會首先去尋找layout-ar目錄下的布局檔案,因此建議刪除layout-ar等bidi語言目錄。layout-ldrtl優先順序又高於解析度等級,優先順序歸納如下:
layout-ar(語言層級) > layout-ldrtl > layout-800*540(解析度)
代碼控制
介紹了以上兩種靜態控制方式後,我們再來看看動態控制bidi語言顯示方式,具體請參考如下代碼:
if ("ar".equals(Locale.getDefault().getLanguage())) { getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL); }以上就是bidi語言涉及的布局修改及配置方式,組合使用以上幾種方式便可以解決我們在國際化中遇到的bidi語言問題。
HashCode當大家閱讀到這兒的時候,可能會存在疑問,Hashcode和語言會有什麼關係呢?其實Hashcode問題才是最終決定我寫這篇部落格的目的。說到Hashcaode我們先來回憶一下Java中hashcode的作用,簡單的說hashcode就是標識對象的唯一標識(備忘:非嚴謹的說法)。最近在開發Android系統開發中遇到這樣一個問題,當手機拍照後正常顯示(表徵圖顯示Camera表徵圖)應該1-1所示:
圖1-1 圖1-2
但是在Azeri和Turkish語言環境中卻顯示成了檔案夾表徵圖,如1-2所示,經過調查最終發現是以下代碼在不同語言環境下Hashcode不同造成的,具體代碼如下所示:
public static int getBucketId(String path) { return path.toLowerCase().hashCode(); }按照以下方式更改後就能正常顯示,具體代碼如下:
public static int getBucketId(String path) { return path.toLowerCase(Locale.ENGLISH).hashCode();//使用英語字元轉換 }Android的解釋資訊如下:
Converts this string to lower case, using the rules of locale.
Most case mappings are unaffected by the language of a Locale. Exceptions include dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in Lithuanian locales. On the other hand, it isn‘t necessary to provide a Greek locale to get correct case mapping of Greek characters: any locale will do.
大概意思就是阿塞拜疆和土耳其語言環境中使用的字元編碼不一樣,我們必須將字元編碼設定成統一的本地編碼這樣Hashcode才保持一致
具體編碼請參考:http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt
總結:Android語言國際化就總結這麼多,希望對大家有所助力;大家如果對語言國際化有新的見解或者更好的實現方式,請在commit中評論,我們共同討論。