Hỗ trợ ngôn ngữ và văn hoá khác

Ứng dụng bao gồm các tài nguyên dành cho một nền văn hoá cụ thể. Ví dụ: một ứng dụng có thể bao gồm các chuỗi văn hoá cụ thể được dịch sang ngôn ngữ của ngôn ngữ hiện tại. Phương pháp tốt là tách biệt các tài nguyên dành riêng cho ngôn ngữ và văn hoá với phần còn lại của ứng dụng. Android phân chia tài nguyên dành riêng cho ngôn ngữ và văn hoá cụ thể dựa trên tuỳ chọn cài đặt ngôn ngữ của hệ thống. Bạn có thể hỗ trợ nhiều ngôn ngữ bằng cách sử dụng thư mục tài nguyên trong dự án Android.

Bạn có thể chỉ định tài nguyên phù hợp với văn hoá của người sử dụng ứng dụng của bạn. Bạn có thể cung cấp mọi loại tài nguyên phù hợp với ngôn ngữ và văn hoá của người dùng. Ví dụ: ảnh chụp màn hình sau đây cho thấy một ứng dụng hiển thị chuỗi và tài nguyên có thể vẽ bằng ngôn ngữ mặc định của thiết bị (en_US) và tiếng Tây Ban Nha (es_ES).

Ứng dụng hiển thị một văn bản và biểu tượng khác tuỳ thuộc vào ngôn ngữ hiện tại

Hình 1. Ứng dụng sử dụng tài nguyên khác nhau tuỳ thuộc vào ngôn ngữ hiện tại

Nếu bạn đã tạo dự án bằng Công cụ SDK Android (đọc bài viết Tạo dự án Android), công cụ sẽ tạo thư mục res/ ở cấp cao nhất của dự án , Trong thư mục res/ này, có nhiều thư mục con dành cho nhiều loại tài nguyên. Ngoài ra, một số tệp mặc định như res/values/strings.xml sẽ lưu giữ các giá trị chuỗi của bạn.

Việc hỗ trợ nhiều ngôn ngữ không chỉ dựa trên tài nguyên dành riêng cho từng ngôn ngữ. Một số người dùng chọn ngôn ngữ viết từ phải sang trái (RTL), như tiếng Ả Rập hoặc Do Thái, cho ngôn ngữ trên giao diện người dùng của họ. Người dùng khác xem hoặc tạo nội dung bằng ngôn ngữ sử dụng chữ viết RTL, dù họ đã đặt ngôn ngữ sử dụng chữ viết từ trái sang phải (LTR), chẳng hạn như tiếng Anh, làm ngôn ngữ giao diện người dùng. Để hỗ trợ cả hai loại người dùng này, ứng dụng của bạn cần làm những việc sau:

  • Sử dụng bố cục giao diện người dùng RTL cho ngôn ngữ RTL.
  • Phát hiện và khai báo hướng của dữ liệu văn bản được hiển thị bên trong tin nhắn có định dạng. Thông thường, bạn chỉ cần gọi một phương thức xác định hướng của dữ liệu văn bản đối với bạn.

Tạo thư mục ngôn ngữ và tệp tài nguyên

Để hỗ trợ thêm nhiều ngôn ngữ, tạo thêm thư mục bên trong res/. Tên của mỗi thư mục phải tuân theo định dạng sau:

<resource type>-b+<language code>[+<country code>]

Ví dụ: values-b+es/ chứa tài nguyên chuỗi cho các ngôn ngữ có mã ngôn ngữ es. Tương tự, mipmap-b+es+ES/ chứa biểu tượng dành cho ngôn ngữ có mã ngôn ngữ es và mã quốc gia ES. Android tải các tài nguyên phù hợp theo chế độ cài đặt ngôn ngữ của thiết bị trong thời gian chạy. Để biết thêm thông tin, xem nội dung Cung cấp tài nguyên thay thế.

Sau khi bạn đã quyết định chọn ngôn ngữ hỗ trợ, tạo các thư mục con và tệp tài nguyên. Ví dụ:

MyProject/
    res/
       values/
           strings.xml
       values-b+es/
           strings.xml
       mipmap/
           country_flag.png
       mipmap-b+es+ES/
           country_flag.png

Ví dụ: dưới đây là một số tệp tài nguyên dành cho các ngôn ngữ khác nhau:

Chuỗi tiếng Anh (ngôn ngữ mặc định), /values/strings.xml:

<resources>
    <string name="hello_world">Hello World!</string>
</resources>

Chuỗi tiếng Tây Ban Nha (ngôn ngữ es), /values-es/strings.xml:

<resources>
    <string name="hello_world">¡Hola Mundo!</string>
</resources>

Biểu tượng cờ của Hoa Kỳ (ngôn ngữ mặc định), /mipmap/country_flag.png:

Biểu tượng cờ của Hoa Kỳ

Hình 2. Biểu tượng dùng cho ngôn ngữ mặc định (en_US)

Biểu tượng cờ của Tây Ban Nha (ngôn ngữ es_ES), /mipmap-b+es+ES/country_flag.png:

Biểu tượng cờ của Tây Ban Nha

Hình 3. Biểu tượng dùng cho ngôn ngữ es_ES

Lưu ý: Bạn có thể sử dụng bộ hạn định ngôn ngữ (hoặc mọi bộ hạn định cấu hình) trên mọi loại tài nguyên, chẳng hạn như nếu bạn muốn cung cấp các phiên bản được bản địa hoá của bitmap có thể vẽ. Để biết thêm thông tin, xem nội dung Bản địa hoá.

Sử dụng tài nguyên trong ứng dụng của bạn

Bạn có thể tham chiếu tài nguyên trong mã nguồn và tệp XML khác bằng cách sử dụng thuộc tính name của từng tài nguyên.

Trong mã nguồn, bạn có thể tham chiếu đến một tài nguyên bằng cú pháp R.<resource type>.<resource name>. Có nhiều phương thức chấp nhận tài nguyên theo cách này.

Ví dụ:

Kotlin

// Get a string resource from your app's Resources
val hello = resources.getString(R.string.hello_world)

// Or supply a string resource to a method that requires a string
TextView(this).apply {
    setText(R.string.hello_world)
}

Java

// Get a string resource from your app's Resources
String hello = getResources().getString(R.string.hello_world);

// Or supply a string resource to a method that requires a string
TextView textView = new TextView(this);
textView.setText(R.string.hello_world);

Trong các tệp XML khác, bạn có thể tham chiếu đến một tài nguyên theo cú pháp @<resource type>/<resource name> bất cứ khi nào thuộc tính XML chấp nhận một giá trị tương thích.

Ví dụ:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@mipmap/country_flag" />

Lưu ý quan trọng: Để đảm bảo cài đặt ngôn ngữ của người dùng được ưu tiên chính xác, chỉ định ngôn ngữ, được ứng dụng của bạn hỗ trợ, bằng thuộc tính resConfigs. Để biết thêm thông tin, xem phần nội dung Chỉ định ngôn ngữ được ứng dụng của bạn hỗ trợ.

Định dạng văn bản trong thông báo

Một trong những nhiệm vụ phổ biến nhất trong ứng dụng là định dạng văn bản. Thông báo được bản địa hoá được định dạng bằng cách chèn dữ liệu văn bản và số vào các vị trí thích hợp. Không may, khi xử lý dữ liệu RTL hoặc giao diện người dùng RTL, định dạng đơn giản có thể hiển thị đầu ra văn bản không chính xác hoặc thậm chí không thể đọc được.

Các ngôn ngữ như tiếng Ả Rập, Do Thái, Ba Tư và Urdu về tổng thể đều được viết theo hướng RTL. Tuy nhiên, một số phần tử trong đó, như số và văn bản LTR nhúng, lại được viết theo hướng LTR trong văn bản theo hướng RTL. Các ngôn ngữ sử dụng chữ viết LTR, gồm cả tiếng Anh, cũng có hai chiều vì các chữ viết này có thể chứa các chữ viết RTL nhúng cần được hiển thị theo hướng RTL.

Trong hầu hết các trường hợp, chính các ứng dụng tạo ra các bản sao văn bản theo hướng ngược lại được nhúng như vậy. Ứng dụng chèn dữ liệu văn bản của một ngôn ngữ tuỳ ý — và một hướng văn bản tuỳ ý — vào các thông báo được bản địa hoá. Việc kết hợp các hướng này thường không bao gồm chỉ báo rõ ràng về nơi văn bản theo hướng ngược lại bắt đầu và kết thúc. Các đặc điểm của văn bản, được ứng dụng tạo ra, gây ra hầu hết các vấn đề.

Dù cách xử lý mặc định đối với văn bản hai chiều của hệ thống thường hiển thị văn bản như dự kiến, nhưng có thể văn bản đó sẽ không hiển thị chính xác khi ứng dụng của bạn chèn văn bản đó vào một thông báo đã bản địa hoá. Dưới đây là ví dụ về những trường hợp rất có khả năng văn bản sẽ không hiển thị chính xác:

  • Được chèn vào ngay đầu thông báo:

    PERSON_NAME đang gọi bạn:

  • Bắt đầu bằng một con số, chẳng hạn như trong địa chỉ hoặc số điện thoại:

    987 654-3210

  • Bắt đầu bằng dấu chấm câu, chẳng hạn như trong số điện thoại:

    +19876543210

  • Kết thúc bằng dấu chấm câu:

    Bạn có chắc không?

  • Chứa sẵn cả hai hướng:

    Từ בננה nghĩa là chuối trong tiếng Do Thái.

Ví dụ

Ví dụ: giả sử một ứng dụng đôi khi cần hiển thị thông báo "Ý của bạn là %s?", với một địa chỉ được chèn vào %s trong thời gian chạy. Vì ứng dụng hỗ trợ nhiều ngôn ngữ giao diện người dùng khác nhau, nên thông báo đến từ tài nguyên dành riêng cho từng ngôn ngữ và sử dụng hướng RTL khi ngôn ngữ RTL được sử dụng. Với giao diện người dùng tiếng Do Thái, thông báo này sẽ hiển thị như sau:

האם התכוונת ל %s?

Tuy nhiên, đề xuất có thể đến từ một cơ sở dữ liệu không bao gồm văn bản bằng ngôn ngữ đó. Ví dụ: nếu địa chỉ được đề cập là một địa điểm tại California, thì địa chỉ đó sẽ xuất hiện trong cơ sở dữ liệu bằng văn bản tiếng Anh. Nếu bạn chèn địa chỉ "15 Bay Street, Laurel, CA" vào thông báo RTL mà không cung cấp bất kỳ gợi ý nào về hướng văn bản, thì kết quả sẽ không như mong đợi hoặc chính xác:

האם התכוונת ל 15 Bay Street, Laurel, CA?

Lưu ý rằng số nhà xuất hiện ở bên phải địa chỉ, chứ không ở bên trái như dự kiến và khiến cho số nhà càng trông như một mã bưu chính lạ. Vấn đề tương tự có thể xảy ra nếu bạn đưa văn bản RTL vào một thông báo sử dụng hướng văn bản LTR.

Giải thích và giải pháp

Vấn đề trong ví dụ trước xảy ra do trình định dạng văn bản không chỉ định rằng "15" là một phần của địa chỉ, vì vậy hệ thống không thể xác định liệu "15" có phải là một phần của văn bản RTL đứng trước hoặc văn bản LTR đứng sau nó không.

Để giải quyết vấn đề này, sử dụng phương thức unicodeWrap() có trong lớp BidiFormatter, trên mọi đoạn văn bản được bạn chèn vào một thông báo đã bản địa hoá. Những lần duy nhất bạn không nên sử dụng unicodeWrap() gồm:

  • Văn bản được chèn vào một chuỗi có thể đọc được bằng máy, chẳng hạn như một URI hoặc một truy vấn SQL.
  • Bạn đã biết đoạn văn bản được gói đúng cách.

Phương thức unicodeWrap() phát hiện hướng của một chuỗi và gói chuỗi đó trong các ký tự theo định dạng Unicode đã khai báo hướng đó. Vì lúc này "15" xuất hiện bên trong văn bản được khai báo là LTR, nên "15" được hiển thị ở đúng vị trí:

האם התכוונת ל 15 Bay Street, Laurel, CA?

Đoạn mã sau đây minh hoạ cách sử dụng unicodeWrap():

Kotlin

val mySuggestion = "15 Bay Street, Laurel, CA"
val myBidiFormatter: BidiFormatter = BidiFormatter.getInstance()

// The "did_you_mean" localized string resource includes
// a "%s" placeholder for the suggestion.
String.format(getString(R.string.did_you_mean), myBidiFormatter.unicodeWrap(mySuggestion))

Java

String mySuggestion = "15 Bay Street, Laurel, CA";
BidiFormatter myBidiFormatter = BidiFormatter.getInstance();

// The "did_you_mean" localized string resource includes
// a "%s" placeholder for the suggestion.
String.format(getString(R.string.did_you_mean),
        myBidiFormatter.unicodeWrap(mySuggestion));

Lưu ý: Nếu ứng dụng của bạn nhắm đến Android 4.3 (API cấp 18) trở lên, dùng phiên bản BidiFormattercó trong Khung Android. Nếu không, sử dụng phiên bản BidiFormatter có trong Thư viện hỗ trợ.

Định dạng số

Dùng chuỗi định dạng, chứ không phải lệnh gọi phương thức, để chuyển đổi số thành các chuỗi trong logic của ứng dụng:

Kotlin

var myIntAsString = "$myInt"

Java

String myIntAsString = String.format("%d", myInt);

Thao tác này sẽ định dạng các số phù hợp với ngôn ngữ của bạn, có thể bao gồm cả việc sử dụng một tập hợp chữ số khác.

Khi bạn sử dụng String.format() để tạo một truy vấn SQL trên thiết bị có ngôn ngữ sử dụng bộ chữ số riêng, chẳng hạn như tiếng Ba Tư và hầu hết tiếng Ả Rập, sự cố xảy ra nếu bất kỳ tham số nào đến truy vấn là số. Điều này là do số được định dạng trong các chữ số của ngôn ngữ và các chữ số này lại không hợp lệ trong SQL.

Để bảo tồn các số được định dạng theo ASCII và giữ cho truy vấn SQL hợp lệ, bạn nên sử dụng phiên bản quá tải của String.format() bao gồm một ngôn ngữ làm tham số đầu tiên. Đối số ngôn ngữ phải là Locale.US.

Hỗ trợ phản chiếu bố cục

Những người sử dụng chữ viết RTL thích giao diện người dùng RTL hơn, chẳng hạn như các trình đơn căn phải, văn bản căn phải và mũi tên tiến lên chỉ sang trái.

Hình 4 cho thấy sự tương phản giữa phiên bản LTR của một màn hình trong ứng dụng Cài đặt và phiên bản RTL của ứng dụng:

Khu vực thông báo được căn phải, nằm gần góc trên cùng bên phải, nút menu trên thanh ứng dụng ở gần góc trên cùng bên trái, nội dung trong phần chính của màn hình được căn trái và hiển thị LTR còn nút quay lại nằm gần góc dưới cùng bên trái và chỉ về bên trái. Khu vực thông báo được căn trái ở gần góc trên cùng bên trái, nút menu trên thanh ứng dụng ở gần góc trên cùng bên phải, nội dung trong phần chính của màn hình được căn phải và hiển thị RTL, còn nút quay lại ở gần góc dưới cùng bên phải và chỉ về bên phải
Hình 4. Các biến thể LTR và RTL của màn hình

Khi thêm hỗ trợ RTL vào ứng dụng, điều đặc biệt quan trọng là bạn cần lưu ý những điểm sau:

Lưu ý: Để xem các hướng dẫn thiết kế khác liên quan đến tính năng phản chiếu bố cục, bao gồm danh sách các yếu tố bạn nên và không nên phản chiếu, xem nội dung hướng dẫn Material Design về Tính hai chiều (Bidirectionality).

Để phản chiếu bố cục giao diện người dùng trong ứng dụng để bố cục hiển thị RTL bằng ngôn ngữ RTL, hoàn tất các bước trong các phần sau.

Sửa đổi tệp bản dựng và tệp kê khai

Sửa đổi tệp build.gradle của mô-đun ứng dụng và tệp kê khai ứng dụng như sau:

build.gradle (Mô-đun: ứng dụng)

Groovy

android {
    ...
    defaultConfig {
        targetSdkVersion 17 // Or higher
        ...
    }
}

Kotlin

android {
    ...
    defaultConfig {
        targetSdkVersion(17) // Or higher
        ...
    }
}

AndroidManifest.xml

<manifest ... >
    ...
    <application ...
        android:supportsRtl="true">
    </application>
</manifest>

Lưu ý: Nếu ứng dụng nhắm đến Android 4.1.1 (API cấp 16) trở xuống, thì thuộc tính android:supportsRtl bị bỏ qua, cùng với mọi giá trị thuộc tính startend xuất hiện trong tệp bố cục của ứng dụng của bạn. Trong trường hợp này, việc phản chiếu bố cục RTL không tự động xảy ra trong ứng dụng của bạn.

Cập nhật tài nguyên hiện có

Lần lượt chuyển đổi left, right thành startend trong từng tệp tài nguyên bố cục hiện có. Khi làm vậy, bạn cho phép khung căn chỉnh các thành phần trên giao diện người dùng của ứng dụng dựa trên chế độ cài đặt ngôn ngữ của người dùng.

Lưu ý: Trước khi cập nhật tài nguyên, tìm hiểu cách hỗ trợ cho ứng dụng cũ hoặc ứng dụng nhắm đến Android 4.1.1 (API cấp 16) và thấp hơn.

Để sử dụng khả năng căn chỉnh RTL của khung, thay đổi các thuộc tính trong các tệp bố cục nằm trong Bảng 1.

Bảng 1. Thuộc tính cần sử dụng khi ứng dụng của bạn hỗ trợ hướng đa văn bản

Thuộc tính chỉ hỗ trợ LTR Thuộc tính hỗ trợ LTR và RTL
android:gravity="left" android:gravity="start"
android:gravity="right" android:gravity="end"
android:layout_gravity="left" android:layout_gravity="start"
android:layout_gravity="right" android:layout_gravity="end"
android:paddingLeft android:paddingStart
android:paddingRight android:paddingEnd
android:drawableLeft android:drawableStart
android:drawableRight android:drawableEnd
android:layout_alignLeft android:layout_alignStart
android:layout_alignRight android:layout_alignEnd
android:layout_marginLeft android:layout_marginStart
android:layout_marginRight android:layout_marginEnd
android:layout_alignParentLeft android:layout_alignParentStart
android:layout_alignParentRight android:layout_alignParentEnd
android:layout_toLeftOf android:layout_toStartOf
android:layout_toRightOf android:layout_toEndOf

Bảng 2 cho thấy cách hệ thống xử lý các thuộc tính căn chỉnh giao diện người dùng trên phiên bản SDK mục tiêu, liệu thuộc tính leftright lẫn thuộc tính startend đã được xác định hay chưa.

Bảng 2. Hành vi căn chỉnh phần tử giao diện người dùng dựa trên phiên bản SDK mục tiêu và các thuộc tính đã xác định

Có nhắm đến Android 4.2
(API cấp 17) trở lên không?
Bên trái và bên phải được xác định chưa? Bắt đầu và kết thúc được xác định chưa? Kết quả
startend đã giải quyết, đồng thời ghi đè leftright
Không Chỉ sử dụng leftright
Không Chỉ sử dụng startend
Không leftright được dùng (startend bị bỏ qua)
Không Không Chỉ sử dụng leftright
Không Không startend đã giải quyết thành leftright

Thêm tài nguyên theo hướng và ngôn ngữ cụ thể

Bước này bao gồm bổ sung các phiên bản cụ thể của tệp bố cục, có thể vẽ và giá trị tài nguyên có chứa giá trị tuỳ chỉnh cho các ngôn ngữ và hướng văn bản khác nhau.

Trong Android 4.2 (API cấp 17) trở lên, bạn có thể sử dụng bộ hạn định tài nguyên -ldrtl (layout-direction-right-to-left) và -ldltr (layout-direction-left-to-to bên phải). Để duy trì khả năng tương thích ngược với tính năng tải tài nguyên hiện có, phiên bản Android cũ sẽ sử dụng các tham số định tính ngôn ngữ của tài nguyên để suy ra hướng văn bản chính xác.

Giả sử bạn muốn thêm tệp bố cục cụ thể để hỗ trợ chữ viết RTL, như tiếng Do Thái, tiếng Ả Rập và tiếng Ba Tư. Để thực hiện việc này, thêm một thư mục layout-ldrtl/ vào thư mục res/, như được thấy trong ví dụ sau:

res/
    layout/
        main.xml This layout file is loaded by default.
    layout-ldrtl/
        main.xml This layout file is loaded for languages using an
                 RTL text direction, including Arabic, Persian, and Hebrew.

Nếu bạn muốn thêm phiên bản cụ thể của bố cục chỉ được thiết kế cho văn bản tiếng Ả Rập, cấu trúc thư mục của bạn sẽ có dạng như sau:

res/
    layout/
        main.xml This layout file is loaded by default.
    layout-ar/
        main.xml This layout file is loaded for Arabic text.
    layout-ldrtl/
        main.xml This layout file is loaded only for non-Arabic
                 languages that use an RTL text direction.

Lưu ý: Tài nguyên dành riêng cho ngôn ngữ được ưu tiên hơn tài nguyên dành riêng cho hướng bố cục. Tài nguyên này lại được ưu tiên hơn tài nguyên mặc định.

Sử dụng tiện ích được hỗ trợ

Kể từ Android 4.2 (API cấp 17), hầu hết các phần tử giao diện người dùng của khung đều tự động hỗ trợ hướng văn bản RTL. Tuy nhiên, một số phần tử khung, như ViewPager, không hỗ trợ hướng văn bản RTL.

Các tiện ích trên màn hình chính hỗ trợ hướng văn bản RTL, miễn là tệp kê khai tương ứng của tiện ích đó bao gồm việc gán thuộc tính android:supportsRtl="true".

Hỗ trợ ứng dụng cũ

Nếu ứng dụng của bạn nhắm đến Android 4.1.1 (API cấp 16) trở xuống, thì ngoài startend, còn phải thêm các thuộc tính leftright.

Để kiểm tra xem liệu bố cục của bạn có cần sử dụng hướng văn bản RTL hay không, sử dụng logic sau:

Kotlin

private fun shouldUseLayoutRtl(): Boolean {
    return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
        View.LAYOUT_DIRECTION_RTL == layoutDirection
    } else {
        false
    }
}

Java

private boolean shouldUseLayoutRtl() {
    if (android.os.Build.VERSION.SDK_INT >=
            android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
        return View.LAYOUT_DIRECTION_RTL == getLayoutDirection();
    } else {
        return false;
    }
}

Lưu ý: Để tránh các vấn đề về khả năng tương thích, sử dụng phiên bản 23.0.1 trở lên của Công cụ xây dựng SDK Android.

Kiểm thử bằng cách sử dụng tuỳ chọn cho nhà phát triển

Trên thiết bị chạy Android 4.4 (API cấp 19) trở lên, bạn có thể bật Buộc hướng bố cục RTL trong các tuỳ chọn cho nhà phát triển trên thiết bị. Tuỳ chọn cài đặt này cho phép bạn xem văn bản sử dụng chữ viết LTR, chẳng hạn như văn bản tiếng Anh, ở chế độ RTL.

Cập nhật logic của ứng dụng

Phần này mô tả các vị trí cụ thể trong logic của ứng dụng mà bạn nên cập nhật khi điều chỉnh ứng dụng để xử lý hướng đa văn bản.

Các thay đổi về thuộc tính

Để xử lý thay đổi trong bất kỳ thuộc tính nào có liên quan đến RTL—chẳng hạn như hướng bố cục, tham số bố cục, khoảng đệm, hướng văn bản, căn chỉnh văn bản hoặc vị trí có thể vẽ—bạn có thể sử dụng lệnh gọi lại onRtlPropertiesChanged(). Lệnh gọi lại này cho phép bạn lấy hướng bố cục hiện tại và cập nhật các đối tượng View của hoạt động cho phù hợp.

Chế độ xem

Nếu bạn đang tạo tiện ích giao diện người dùng mà không trực tiếp nằm trong hệ phân cấp chế độ xem của hoạt động, chẳng hạn như hộp thoại hoặc phần tử giao diện người dùng kiểu thông báo ngắn, thì đặt hướng bố cục chính xác tuỳ thuộc vào ngữ cảnh. Đoạn mã sau đây cho thấy cách hoàn tất quy trình này:

Kotlin

val config: Configuration = context.resources.configuration
view.layoutDirection = config.layoutDirection

Java

final Configuration config =
    getContext().getResources().getConfiguration();
view.setLayoutDirection(config.getLayoutDirection());

Một số phương thức của lớp View cần được xem xét thêm:

onMeasure()
Kích thước chế độ xem có thể thay đổi tuỳ theo hướng văn bản.
onLayout()
Nếu tự tạo triển khai bố cục riêng, thì bạn cần gọi super() trong phiên bản của onLayout() và điều chỉnh logic tuỳ chỉnh để hỗ trợ chữ viết RTL.
onDraw()
Nếu đang triển khai chế độ xem tuỳ chỉnh hoặc thêm chức năng nâng cao vào một bản vẽ, bạn sẽ cần cập nhật mã để hỗ trợ chữ viết RTL. Sử dụng mã sau để xác định liệu tiện ích của bạn có đang ở chế độ RTL hay không:

Kotlin

// On devices running Android 4.1.1 (API level 16) and lower,
// you can call the isLayoutRtl() system method directly.
fun isLayoutRtl(): Boolean = layoutDirection == LAYOUT_DIRECTION_RTL

Java

// On devices running Android 4.1.1 (API level 16) and lower,
// you can call the isLayoutRtl() system method directly.
public boolean isLayoutRtl() {
    return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
}

Đối tượng có thể vẽ

Nếu một đối tượng có thể vẽ cần được phản chiếu cho bố cục RTL, thì hoàn thành một trong các bước này dựa trên phiên bản Android đang chạy trên thiết bị:

  • Trên các thiết bị chạy Android 4.3 (API cấp 18) trở xuống, bạn cần thêm và xác định các tệp tài nguyên -ldrtl.
  • Trên Android 4.4 (API cấp 19) trở lên, bạn có thể sử dụng android:autoMirrored="true" khi xác định đối tượng có thể vẽ để cho phép hệ thống xử lý việc phản chiếu bố cục RTL cho bạn.

    Lưu ý: Thuộc tính android:autoMirrored chỉ hoạt động đối với các đối tượng có thể vẽ đơn giản mà chế độ phản chiếu hai chiều của đối tượng đó chỉ là phản chiếu đồ hoạ của toàn bộ đối tượng có thể vẽ. Nếu đối tượng có thể vẽ chứa nhiều phần tử hoặc nếu việc phản ánh đối tượng có thể vẽ của bạn làm thay đổi phần diễn giải của đối tượng, bạn nên tự thực hiện việc phản chiếu. Mỗi khi có thể, kiểm tra với một chuyên gia hai chiều để xác định liệu các đối tượng có thể vẽ được phản chiếu có phù hợp với người dùng hay không.

Trọng tâm

Nếu mã của ứng dụng đang sử dụng Gravity.LEFT hoặc Gravity.RIGHT, thì bạn cần lần lượt thay đổi các giá trị này thành Gravity.STARTGravity.END.

Ví dụ: nếu bạn đang sử dụng mã sau:

Kotlin

when (gravity and Gravity.HORIZONTAL_GRAVITY_MASK) {
    Gravity.LEFT -> {
        // Handle objects that are left-aligned.
    }
    Gravity.RIGHT -> {
        // Handle objects that are right-aligned.
    }
}

Java

switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
    case Gravity.LEFT:
        // Handle objects that are left-aligned.
        break;
    case Gravity.RIGHT:
        // Handle objects that are right-aligned.
        break;
}

...thì bạn cần thay đổi mã thành như sau:

Kotlin

val absoluteGravity: Int = Gravity.getAbsoluteGravity(gravity, layoutDirection)
when (absoluteGravity and Gravity.HORIZONTAL_GRAVITY_MASK) {
    Gravity.LEFT -> {
        // Handle objects that are left-aligned.
    }
    Gravity.RIGHT -> {
        // Handle objects that are right-aligned.
    }
}

Java

final int layoutDirection = getLayoutDirection();
final int absoluteGravity =
        Gravity.getAbsoluteGravity(gravity, layoutDirection);
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
    case Gravity.LEFT:
        // Handle objects that are left-aligned.
        break;
    case Gravity.RIGHT:
        // Handle objects that are right-aligned.
        break;
}

Điều này có nghĩa là bạn có thể giữ mã hiện có để xử lý các giá trị được căn trái và được căn phải, ngay cả khi bạn đang sử dụng startend cho các giá trị trọng tâm của mình.

Lưu ý: Khi áp dụng các tuỳ chọn cài đặt trọng tâm, sử dụng phiên bản quá tải của Gravity.apply() gồm cả đối số layoutDirection.

Lề và khoảng đệm

Để hỗ trợ chữ viết RTL trong ứng dụng của bạn, làm theo các phương pháp hay nhất liên quan đến giá trị lề và khoảng đệm:

  • Sử dụng getMarginStart()getMarginEnd() thay vì đối số tương đương của thuộc tính hướng cụ thể, leftMarginrightMargin.
  • Khi sử dụng setMargins(), hoán đổi các giá trị của đối số leftright nếu ứng dụng của bạn phát hiện chữ viết RTL.
  • Nếu ứng dụng của bạn chứa logic khoảng đệm tuỳ chỉnh, ghi đè setPadding()setPaddingRelative().

Xem thêm

Tài nguyên khác

Để tìm hiểu thêm về cách hỗ trợ thiết bị cũ, xem các tài nguyên sau:

Bài đăng trên blog