Android: Tất Tần Tật Về Alternative Resource

Posted by

Được chỉnh sửa ngày 25/3/2017.

Chào mừng các bạn đến với các bài viết bổ sung cho chương trình học Android của Yellow Code Books.

Qua bài học Android số 8 thì bạn cũng biết rằng resource đóng một vai trò quan trọng trong việc phát triển một ứng dụng. Trong đó nếu bạn biết rõ và sử dụng tốt một dạng nâng cấp của resource (hay còn gọi là default resource), đó chính là alternative resource, thì còn có thể giúp cho ứng dụng trở nên thông minh hơn mà không tốn bất kỳ dòng code Java nào. Chẳng hạn như ở bài thực hành của bài học số 8, khi đó bạn đã làm cho ứng dụng TourNote có thể biết khi nào nên hiển thị ngôn ngữ trong app là tiếng Anh, khi nào là tiếng Việt.

Vậy bài viết hôm nay mình sẽ tập trung làm cách nào định nghĩa rõ ràng về alternative resource, và nói rõ cách thức sử dụng chúng luôn nhé.

Định Nghĩa Về Alternative Resource

Theo như định nghĩa ở Bài học số 8, thì alternative resource có thể hiểu là các resource có chọn lựa. Ngược lại với default resource là các resource mà bạn không cần quan tâm chúng hiển thị thế nào cho từng loại thiết bị. Thì alternative resource là các resource mà bạn chính là người phải chỉ định cho hệ thống biết khi nào nên dùng resource nào, tức là có sự chọn lựa resource theo ý bạn. Bạn hãy nhìn vào hình minh họa sau.

resource_devices_diagram2

Hình minh họa trên có nghĩa là, giả sử bạn có một layout theo chuẩn alternative resource, khi đó bạn có thể chỉ định rõ cho hệ thống rằng nếu ứng dụng chạy trên phone (như hình bên trái) thì hãy hiển thị layout đó dạng list, còn nếu ứng dụng chạy trên tablet (hình bên phải) thì hãy hiển thị layout dạng table.

Vậy cách thức chỉ định cho hệ thống như thế nào mời bạn xem tiếp bước sau.

Cách Sử Dụng Alternative Resource

Cách sử dụng alternative resource rất đơn giản, bạn vẫn dựa vào cách thức tổ chức resource theo dạng thư mục như là default resource, bạn chỉ cần thêm một điều kiện vào cuối tên của mỗi thư mục đó để hệ thống biết khi nào nên load resource nào mà thôi.

Công thức cụ thể cho alternative resource như sau.

-

Trong đó default_resource là các thư mục con của res/ mà mình có nhắc đến ở bài 8, bài viết này mình xin phép không nhắc lại nữa. Còn config_qualifier là phần chỉ định cho hệ thống khi nào nên dùng đến resource nào. Bài viết này tập trung vào tất cả các config_qualifier có trong Android.

Lưu ý là thứ tự xuất hiện của các config_qualifier trong bài viết hôm nay sẽ được mình cho xuất hiện theo độ ưu tiên giảm dần từ trên xuống. Muốn biết độ ưu tiên này có ý nghĩa gì thì bạn hãy cố gắng đọc đến cuối bài viết này nhé.

Chúng ta hãy bắt đầu liệt kê các config_qualifier nào.

Config Theo MCC và MNC

Đầu tiên mình sẽ nói rõ hơn về MCC và MNC cho bạn nào chưa biết. MCC (Mobile Country Code)MNC (Mobile Network Code) là hai giá trị được lấy lên từ SIM card. Trong đó MCC sẽ cho biết SIM đó thuộc quốc gia nào, còn MNC sẽ cho biết nhà mạng mà SIM đó đang thuộc về.

Để biết rõ hơn về các giá trị của chúng thì bạn có thể tra cứu thêm ở trang này.

Việc config theo MCC và MNC có thể được dùng cho các mục đính liên quan đến các điều khoản sử dụng theo từng nhà mạng. Bạn không nên dùng config này trong việc hỗ trợ đa ngôn ngữ. Nếu cần hỗ trợ đa ngôn ngữ cho ứng dụng thì bạn có thể bỏ qua cách config này mà xem cách config tiếp theo.

Cách Thức Config

Giả sử bạn muốn tách string resoure giữa hai nhà mạng Vinaphone và Mobifone của Việt Nam, thì bạn hãy tạo các thư mục như sau rồi định nghĩa string tương ứng cho nó.

res/
    values-mcc452-mnc02/
        strings.xml    (nhà mạng Vinaphone)
    values-mcc452-mnc01/
        strings.xml    (nhà mạng Mobifone)

Có một điều bạn nên nhớ, đó là bạn không thể khai báo như sau res/values-mnc01-mcc452, khi này hệ thống sẽ báo lỗi vì mcc phải được ưu tiên cao hơn mnc và vì vậy mcc phải đứng trước mnc trong khai báo.

Config Theo Ngôn Ngữ Và Quốc Gia

Tiêu đề đã nói lên tất cả. Config này giúp ứng dụng phân biệt resource theo Ngôn Ngữ và Quốc Gia. Ngôn ngữ sẽ là hai ký tự được lấy theo bảng sau ở cột ISO 639-1. Còn quốc gia thì cũng là hai ký tự được lấy theo bảng sau ở cột Alpha-2 code.

Cách thức config

Ngôn ngữ được khai báo đầu tiên với hai ký tự, kế đến là quốc gia với hai ký tự (bạn nhớ là phải luôn có chữ r ở trước quốc gia, chữ r này là ký tự viết tắt của chữ region). Các ký tự này không phân biệt chữ hoa thường. Ví dụ bạn muốn phân biệt tiếng Anh chung chung, tiếng Anh-Mỹ, và tiếng Anh-Anh thì hãy tạo các thư mục như sau.

res/
    values-en/
        strings.xml    (tiếng Anh chung chung)
    values-en-rGB/
        strings.xml    (tiếng Anh-Anh)
    values-en-rUS/
        strings.xml    (tiếng Anh-Mỹ)

Config Theo Hướng Bố Cục

Uhm… mình chưa từng dùng tới config này bao giờ, nhưng mình biết lý do của config này ra đời. Chắc các bạn cũng biết rằng chữ viết Ả Rập (Arabic) là một trong các hệ chữ đặc biệt được viết theo hướng từ phải sang trái? Cách viết này ngược với chữ viết của ta và của nhiều ngôn ngữ khác trên thế giới.

Khi đó thì config này ra đời nhằm phục vụ một số mục đích bố cục theo hướng viết cho các quốc gia. Mặc định thì mọi thứ đều bố cục từ trái sang phải nên nếu bạn không chỉ định gì cả và ứng dụng bạn chắc chắn không phân phối ở các quốc gia đặc biệt như các nước Ả Rập thì không lo lắng gì cả nhé. Nhưng nếu bạn muốn hỗ trợ cách viết từ phải sang trái thì hãy xem cách config sau.

Cách thức config

Dĩ nhiên là sẽ có hai dạng config, đó là -ldrtl (layout-direction-right-to-left)-ldltr (layout-direction-left-to-right). Khi đó các thư mục sẽ được tổ chức như sau.

res/
    layout-ldrtl/
        main.xml    (layout default)
    layout-ldrtl/
        main.xml    (layout hỗ trợ bố cục phải sang trái)

Config Bằng Cách Chỉ Định Độ Rộng Nhỏ Nhất Của Màn Hình

Config này được hỗ trợ từ API level 13 tuy nhiên config kiểu này đã bị lỗi thời, khi mà ngày nay các resource được phân biệt theo mật độ điểm ảnh density (ldpi, mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi) sẽ tỏ ra hiệu quả hơn. Vậy cách config này chỉ còn thích hợp cho một số trường hợp thực sự đặc biệt, hay với các thiết bị cũ ngày xưa.

Cách thức config

Bạn chỉ cần chỉ định -swdp. Với N là chỉ định độ rộng nhỏ nhất (tính theo dp) của màn hình khi ở chế độ portrait, tức là chế độ màn hình đứng. Như vậy thì dù cho màn hình có là đứng hay ngang thì cách hệ thống so sánh sẽ không thay đổi.

Một ví dụ cho trường hợp sử dụng config này, chẳng hạn như bạn muốn hỗ trợ layout đặc biệt cho một thiết bị nào đó với màn hình 7″ trở lên, còn các màn hình nhỏ hơn thì vẫn xài default. Bạn biết rằng với kích thước màn hình đó thì chiều rộng nhỏ nhất của chúng trong khoảng 3.5″ tới 3.75″, thiết bị đó có mật độ điểm ảnh 160dp (tức 1 inch có 160 px), vậy tính ra độ rộng tối thiểu (shortest width hay sw) của thiết bị này là từ 560dp đến 600dp. Và bạn sẽ tạo ngay và luôn thư mục sau để hộ trợ layout cho thiết bị đặc biệt này.

res/
    layout/
        main.xml    (layout cho các thiết bị khác)
    layout-sw600dp/
        main.xml    (layout cho thiết bị đặc biệt 7")

Config Bằng Cách Chỉ Định Chiều Rộng Và Cao Của Màn Hình

Cũng giống với config trên nhưng các này thay vì chỉ định độ rộng nhỏ nhất cho màn hình, thì sẽ chỉ định đúng độ rộng hoặc cao của màn hình.

Trường hợp này config sẽ được xác định lại khi hướng của màn hình thay đổi (để đứng hay xoay ngang) để phù hợp với chiều rộng hoặc cao hiện tại của màn hình.

Cách Thức Config

Tương tự như trên, bạn có thể config bằng cách thêm vào -wdp hay -hdp. Trong đó N vẫn là chiều rộng hay cao của màn hình.

res/
    layout-w720dp/
    layout-h720dp/

Config Theo Kích Thước Màn Hình

Config theo kích thước màn hình cũng là một cách config xa xưa, cũng giống như hai cách trên đây, cách config này cũng đã lỗi thời. Nguyên nhân là ngày xưa khi thiết bị Android còn ở các version đầu, các nhà sản xuất đều chưa tung ra các màn hình với mật độ điểm ảnh khác nhau, mà chỉ tập trung vào kích thước màn hình mà thôi. Do đó config chủ yếu là nhằm vào phân biệt dựa trên kích thước màn hình nhỏ, vừa, lớn, và rất lớn. Ngày nay thì màn hình nhỏ chưa chắc mật độ điểm ảnh nhỏ, và ngược lại màn hình lớn chưa chắc đã mịn và đẹp như màn hình nhỏ, nên giờ đây bạn nên config dựa trên density (ldpi, mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi) là tốt nhất.

Cách Thức Config

Các giá trị mà bạn có thể dùng để config theo kích thước màn hình là.

-small: cho các màn hình từ 3″ trở xuống, tính theo đường chéo màn hình.
-normal: cho các màn hình từ 3″ đến 5″, tính theo đường chéo màn hình.
-large: cho các màn hình từ 5″ đến 10″, tính theo đường chéo màn hình.
-xlarge: cho các màn hình lớn hơn 10″, tính theo đường chéo màn hình.

Như vậy với ví dụ về việc tách resource ảnh cho các màn hình như trên bạn có thể phân cấp thư mục như sau.

res/
    drawable-small/
    drawable-normal/
    drawable-large/
    drawable-xlarge/

Config Theo Diện Mạo Màn Hình

Lại một kiểu config cổ và quái dị nữa, cách này sẽ phân biệt resource vào các dạng màn hình dài và không dài, cách này cũng rất cổ xưa rồi, nó xuất hiện từ API level 4. Màn hình dài tức các màn hình rộng về chiều ngang, như các kích cỡ WQVGA, WVGA, FWVGA. Các màn hình không dài như QVGA, HVGA và VGA.

Cách Thức Config

Bạn chỉ cần chỉ định long (dài) hay notlong (không dài) cho config này.

res/
    layout-long/
    layout-notlong/

Config Theo Màn Hình Tròn

Mới đọc tưởng đâu đây cũng là cách cổ, nhưng không, cách config này xuất hiện từ API level 23, chỉ mới đây thôi, ra đời để giúp bạn phân biệt giữa màn hình tròn như các thiết bị đeo được, và màn hình không tròn như phone và tablet.

Cách Thức Config

Bạn chỉ cần chỉ định -round cho màn hình tròn, và -notround cho màn hình không tròn.

res/
    values-round/
    values-notround/

Config Theo Hướng Xoay Của Màn Hình

Cách này quan trọng, giúp bạn chỉ định reaource nào dành cho màn hình đứng, và resource nào dành cho màn hình xoay ngang.

Cách Thức Config

Bạn chỉ định -port cho màn hình đứng (portrait) và -land cho màn hình ngang (landscapse). Như ví dụ sau.

res/
    layout-port/
    layout-land/

Config Theo UI Mode

Thiết bị Android của user có thể được cắm vào trong các dock (đế). Có những dock chỉ là để đỡ điện thoại, cũng có dock là một thiết bị nào đó có tính tương tác với thiết bị của user. Cách thức config này sẽ cho app của bạn nhận biết và hỗ trợ với các dock khác nhau.

Cách Thức Config

Bạn có thể chỉ định các UI mode sau đây cho app của mình.

-car: hỗ trợ hiển thị với car dock, các dock trên xe hơi.
-desk: hỗ trợ hiển hị với desk dock, các dock để bàn.
-television: hỗ trợ hiển thị trên ti-vi
-appliance: hỗ trợ như là một thiết bị phụ trợ, không cần hiển thị.
-watch: hiển thị trên các thiết bị đeo được.

Ví dụ.

res/
    layout-car/
    layout-desk/
    layout-television/
    layout-appliance/
    layout-watch/

Config Theo Chế Độ Ban Đêm

Config theo chế độ này có thể giúp app của bạn hiển thị với các resource khác nhau giữa ban ngày và ban đêm, dựa vào thời gian của hệ thống.

Cách Thức Config

Bạn chỉ định -night cho resource theo chế độ ban đêm và -notnight cho resource chế độ ban ngày. Ví dụ.

res/
    layout-night/
    layout-notnight/

Config Theo Mật Độ Điểm Ảnh – Density

Đây là cách hỗ trợ đa màn hình tốt nhất hiện nay, khi mà trên thị trường có rất nhiều thiết bị với rất nhiều kích cỡ màn hình cùng rất nhiều tỉ lệ điểm ảnh khác nhau, khi đó việc config dựa trên kích cỡ màn hình thôi như các cách trên là lỗi thời và việc dựa vào mật độ điểm ảnh sẽ hợp lý hơn nhiều.

Cách Thức Config

Bạn có thể phân biệt resource dựa trên các mật độ điểm ảnh sau.

-ldpi: dành cho các màn hình có mật độ điểm ảnh thấp, xấp xỉ 120dpi. Các màn hình với mật độ điểm ảnh thấp này dường như không còn hoặc còn rất ít trên thị trường nên bạn chú ý có thể không cần hỗ trợ resource theo config màn hình dạng này.
-mdpi: dành cho các màn hình có mật độ điểm ảnh trung bình, xấp xỉ 160dpi.
-hdpi: dành cho các màn hình có mật độ điểm ảnh cao, xấp xỉ 240dpi.
-xhdpi: dành cho các màn hình có mật độ điểm ảnh siêu-cao (extra-high), xấp xỉ 320dpi. Mật độ diểm ảnh này được thêm vào từ API level 8.
-xxhdpi: dành cho các màn hình có mật độ điểm ảnh siêu-siêu-cao (extra-extra-high), xấp xỉ 480dpi. Mật độ diểm ảnh này được thêm vào từ API level 16.
-xxxhdpi: dành cho các màn hình có mật độ điểm ảnh siêu-siêu-siêu-cao (extra-extra-extra-high), xấp xỉ 640dpi. Mật độ diểm ảnh này được thêm vào từ API level 18.
-nodpi: dùng để chứa các resource mà không muốn bị co dãn theo tỉ lệ màn hình.
-tvdpi: dành cho các màn hình có mật độ điểm ảnh trong khoảng giữa của mdpi và hdpi, xấp xỉ 213dpi. Mật độ điểm ảnh này dành cho ti-vi, với đa số các app hiện nay nếu không hỗ trợ cho ti-vi thì bạn không cần quan tâm đến config này cũng được.
-anydpi: dùng để chứa các resource dùng được cho tất cả các thể loại màn hình, tất nhiên là resource này sẽ không bị bể khi bị co dãn thoải mái ở các dạng màn hình khác nhau, đơn cử cho loại resource này đó chính là vector drawable. Nếu bạn nào quan tâm đến vector drawable thì có thể xem qua ở đây. Nhưng drawable dạng này chỉ mới xuất hiện từ API level 21 nên tính phổ biến cũng chưa cao.

Ví dụ.

res/
    layout-mdpi/
    layout-hdpi/
    layout-xhdpi/
    layout-xxhdpi/
    layout-xxxhdpi/

Config Theo Màn Hình Cảm Ứng Hay Không

Bạn đừng vội cười khi thấy có phân biệt màn hình cảm ứng hay không ư, xin thưa là đây cũng là một trong những config quan trọng trong Android, có rất nhiều thiết bị Android trên thị trường không có chức năng cảm ứng, như SmartTV chẳng hạn.

Cách Thức Config

Bạn chỉ định -notouch cho thiết bị không có màn hình cảm ứng, còn -finger là thiết bị có màn hình cảm ứng. Ví dụ.

res/
    layout-notouch/
    layout-finger/

Config Theo Loại Bàn Phím Ảo/Vật Lý

Cách này phân biệt resource dựa trên loại bàn phím ảo (softkey) hay bàn phím vật lý (keyboard) sử dụng trong thiết bị.

Cách Thức Config

Việc config theo loại bàn phím này dựa trên các giá trị sau.

-keysexposed: khi thiết bị có bàn phím, dù là bàn phím vật lý hoặc bàn phím ảo (thường thì các thiết bị Android dùng bàn phím ảo). Chỉ khi thiết bị không cho phép bàn phím ảo và cũng không có bàn phím vật lý thì config này mới không được dùng đến.
-keyshidden: khi thiết bị không cho phép bàn phím ảo, và bàn phím vật lý bị ẩn đi.
-keyssoft: khi thiết bị có cho phép bàn phím ảo, dù nó có hiện ra hay không, vậy thì 99% sẽ rơi vào config này nếu bạn thêm config này vào resource.

Config Theo Loại Bàn Phím Vật Lý

Cách này khác cách phân biệt trên ở chỗ không phân biệt bàn phím ảo hay vật lý, mà sẽ config theo các thể loại bàn phím vật lý hiện nay trên thị trường, các loại đó được liệt kê ở mục sau.

Cách Thức Config

Có các thể loại bàn phím vật lý sau.

-nokeys: thiết bị không có bàn phím vật lý nào cả, thiết bị này dùng bàn phím ảo.
-qwerty: thiết bị có bàn phím vật lý dạng qwerty.
12key: thiết bị có bàn phím vật lý theo kiểu xa xưa với 12 phím bố trí theo dạng lưới 3×4.

Config Theo Các Thiết Bị Điều Hướng

Các thiết bị điều hướng là thiết bị vật lý bổ sung giúp điều khiển con trỏ hay chọn lựa các thành phần UI trên màn hình.

Cách Thức Config

Có các cách thức điều hướng sau.

-nonav: không có thiết bị điều hướng.
-dpad: thiết bị điều hướng là một nút bự với 4 hướng khác nhau mà bạn hay gặp trong các điện thoại ngày xưa.
-trackpad: thiết bị điều hướng là bàn rê cảm ứng giống như có ở trên các máy laptop.
-trackball: thiết bị điều hướng là một viên bi, giống như trên các điện thoại Blackberry ngày xưa.
-wheel: thiết bị điều hướng là một bánh xe, giống như bánh xe trên con chuột vi tính của bạn.

Config Theo Platform Version

Có nhiều trường hợp bạn cần hỗ trợ resource cho các API version cụ thể nào đó, chẳng hạn các version cũ nào đó mà resource chưa dùng được các thuộc tính như các resource ở version mới, thì cách config theo platform version này sẽ rất hiệu quả.

Cách Thức Config

Bạn chỉ cần có tiền tố v và theo sau version của parform đó là xong.

-v3: resource hỗ trợ API level 3
-v4: resource hỗ trợ API level 4
-v7: resource hỗ trợ API level 7
-v…

Ví dụ.

res/
    layout-v11/
    layout-v7/

Một Số Quy Tắc Của Alternative Resource

Ở trên mình có liệt kê tất cả các config có thể có để bạn có thể làm ra các sản phẩm chất lượng.

Nhưng bạn cũng biết rằng chúng ta hoàn toàn có thể kết hợn nhiều config lại vào trong một thư mục resource, chỉ cần để chúng cách nhau bởi dấu “-“ thôi. Và khi đó thì chắc chắn hệ thống sẽ cần đến một số quy tắc nào đó để phân biệt việc chọn lựa từng loại resource. Vậy phần này mình xin nói rõ hơn các quy tắc này để bạn tránh khỏi các thông báo lỗi nhé.

  • Bạn có thể chỉ định nhiều config qualifier trong một thư mục resource duy nhất. Chẳng hạn như bạn khai báo res/drawable-en-rUS-land/, đây là resource dùng cho thiết bị khi ngôn ngữ là tiếng Anh-Mỹ, và màn hình thiết bị đang xoay ngang.
  • Thứ tự của các config qualifier trong cùng một thư mục phải theo thứ tự từ trên xuống dưới đã được mình liệt kê ở mục “Cách Sử Dụng Alternative Resource” trên. Ví dụ:
    • Sai: drawable-hdpi-port/
    • Đúng: drawable-port-hdpi/
  • Các thư mục alternative resource không được lồng vào nhau. Ví dụ bạn không thể có resource kiểu này được res/drawable/drawable-en/.
  • Tên được đặt cho các thư mục sẽ không phân biệt chữ hoa-thường, có nghĩa là bạn cứ đặt hoa-thường thoải mái, khi biên dịch thì hệ thống sẽ chuyển hết thành chữ thường mà thôi.
  • Cứ với mỗi cách config ở mục trên bạn chỉ được khai báo 1 lần trong cùng một thư mục, ví dụ bạn không thể hỗ trợ resource cho cả Spain và France bằng cách config res/drawable-rES-rFR/ được, mà phải tách ra làm 2 resource khác nhau res/drawable-rES/res/drawable-rFR/.

Android Chọn Resource Theo Tiêu Chí Nào

Nếu bạn nào chưa đủ nhức đầu thì đọc tiếp phần này, không thì dừng lại cũng được rồi. Phần này nói về việc dù cho bạn có cẩn thận tạo ra các alternative resource một cách chuyên nghiệp, thì cũng không thể đảm bảo chúng sẽ được load chính xác trên từng cấu hình của thiết bị ngoài thị trường. Vì vậy nếu không thể load chính xác resource thì Android sẽ sử dụng một số tiêu chí để chọn lựa ra một resource mang tính chính xác nhất có thể theo cấu hình hiện tại của thiết bị, và chúng ta nói về các tiêu chí này.

Tiêu Chí

Đầu tiên, Android sẽ bỏ qua tất cả các config resource không hợp lệ. Ví dụ như Android phát hiện ra ngôn ngữ của máy là tiếng Việt, nó sẽ tìm đến thư mục có config là -vi, và sẽ bỏ qua tất cả các config còn lại (như -en, -fr,…).

Nếu vẫn chưa tìm ra thư mục cần load, Android sẽ dựa trên độ ưu tiên của thư mục bằng cách duyệt tuần tự từ trái qua các config trên tên của resource đó.

Nếu cuối cùng vẫn không tìm ra thư mục cần load, Android sẽ load thư mục default.

Để hiểu rõ hơn chúng ta qua các kịch bản ví dụ sau.

Kịch Bản 1

Giả sử mình đặt file main.xml vào trong hai thư mục sau.

res/
    layout-land/
        main.xml
    layout/
        main.xml

Nếu thiết bị của mình đang là xoay ngang (landscape), thì bạn nghĩ file main.xml trong thư mục nào sẽ được load lên?

Chắc chắn là file main.xml trong thư mục res/layout-land/ sẽ được ưu tiên load lên rồi. Ngược lại nếu thiết bị để dọc, khi này res/layout-land/ sẽ bị loại bỏ, vậy chỉ còn lại file main.xml trong res/layout/ khi đó sẽ được load lên.

Kịch Bản 2

Cũng file main.xml được đặt trong các thư mục sau.

res/
    layout-en/
        main.xml
    layout-land/
        main.xml
    layout/
        main.xml

Nếu thiết bị của mình đang là tiếng Anh và đang xoay ngang, file main.xml trong thư mục nào sẽ được load?

Kết quả là main.xml trong res/layout-en/ được ưu tiên bất kể màn hình ngang hay dọc, vì trong trường hợp này config -en có thứ tự cao hơn config -land. Nếu thiết bị không phải tiếng Anh, thư mục res/layout-en/ bị loại bỏ, vấn đề còn lại sẽ y như Kịch Bản 1.

Kịch Bản 3

Tiếp tục file main.xml trong các thư mục sau.

res/
    layout-en/
        main.xml
    layout-land-v11/
        main.xml
    layout/
        main.xml

Giả sử thiết bị của mình đang là tiếng Anh, màn hình xoay ngang, và Android API level 11, thì theo bạn main.xml trong thư mục res/layout-land-v11/ có được chọn không?

Câu trả lời là: Không! 🙂

Kịch bản này cũng được giải thích giống như Kịch Bản 2, mình cố tình tăng độ quan trọng của việc khớp với hai config là -land-v11 để cho bạn bị nhầm là thư mục res/layout-land-v11/ sẽ được ưu tiên, nhưng bạn nên hiểu một khi ngôn ngữ là tiếng Anh thì lựa chọn res/layout-en/ là quan trọng nhất.

Kịch Bản 4

Giờ thì giả sử file main.xml nằm trong 3 thư mục sau.

res/
    layout-land-night/
        main.xml
    layout-land-v11/
        main.xml
    layout/
        main.xml

Tình huống này chúng ta thấy -land đều được ưu tiên cao, vậy trong 2 config qualifier tiếp theo thì config nào sẽ được ưu tiên tiếp theo? Dĩ nhiên là -night cao hơn -v11 rồi đúng không nào. Do đó khi thiết bị xoay ngang và ở night mode thì Android sẽ chọn res/layout-land-night/ dù cho API level đang là v11. Và nếu thiết bị không phải night mode hay v11 thì res/layout/ sẽ được chọn.

Kịch Bản 5

Bạn thấy các cách chọn lựa resource trên đây của Android khá rõ ràng và đúng nguyên tắc phải không nào. Nhưng có một config mà Android sẽ phải sử dụng tiêu chí “gần đúng nhất” thay cho sự “chính xác”, đó chính là config về mật độ điểm ảnh (density). Vì trên thị trường có vô số các thiết bị với các cấu hình về mật độ điểm ảnh khác nhau, nhưng với config theo density này bạn chỉ có vỏn vẹn vài loại resource mà thôi như -mdpi, -hpi, -xhdpi, -xxhdpi, -xxxhdpi,… Vậy nên Android sẽ quyết định tìm ra resource nào gần nhất với các config thuộc loại này mà không phải là chính xác.

Vậy giả sử mình có file main.xml trong các thư mục sau đây.

res/
    layout-mdpi/
        main.xml
    layout-nonav/
        main.xml
    layout/
        main.xml

Và giả sử thiết bị của mình có density là hdpi và không có thiết bị điều hướng (nonav) thì file main.xml trong thư mục nào sẽ được chọn?

Kết quả là, theo như mình vừa nói thì nếu có config dạng density, Android sẽ dùng phương pháp chọn gần đúng nhất, trong trường hợp này tuy không có config là -hdpi nhưng Android sẽ tìm đến -mdpi thay thế, và vì vậy res/layout-mdpi/ sẽ được chọn trong tình huống này.

Và bài viết này đã kết thúc. Tuy dài nhưng mình hi vọng nó sẽ giúp ích cho bạn khá nhiều trong việc viết một ứng dụng Android thông minh và hữu dụng. Biết đâu qua bài viết này bạn có thể sẽ nghĩ ra một ý tưởng hay để viết ứng dụng cho riêng mình? Chúc các bạn thành công!

Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy đánh giá 5 sao nếu thấy thích bài viết, hãy comment bên dưới nếu có thắc mắc, hãy để lại địa chỉ email của bạn để nhận được thông báo mới nhất khi có bài viết mới, và nhớ chia sẻ các bài viết của Yellow Code Books đến nhiều người khác nữa nhé.

Advertisements
Rating: 5.0. From 8 votes.
Please wait...

4 comments

Gửi phản hồi