Làm tối nội dung trên web trong WebView

Trên Android 10 trở lên, một ứng dụng có thể hỗ trợ Giao diện tối và tự động thay đổi giữa các giao diện sáng và tối của ứng dụng theo giao diện hệ thống. Để phù hợp với giao diện ứng dụng hiện tại, nội dung web trong WebView cũng có thể sử dụng kiểu sáng, tối hoặc mặc định.

Hành vi của WebView tương tác với các tiêu chuẩn web prefers-color-schemecolor-scheme. Bất cứ khi nào có thể, nếu là tác giả của nội dung trên web mà bạn muốn ứng dụng của mình hiển thị trong WebView, bạn nên xác định giao diện tối cho trang web của mình và triển khai prefers-color-scheme để WebView có thể phù hợp với giao diện của nội dung web với giao diện của ứng dụng.

Bảng sau đây mô tả cách WebView hiển thị nội dung trên web trong ứng dụng của bạn, tuỳ thuộc vào kiểu của nội dung web và các điều kiện của ứng dụng:

Các điều kiện về ứng dụng Nội dung web sử dụng prefers-color-scheme Nội dung web không sử dụng prefers-color-scheme
Ứng dụng đang sử dụng giao diện sáng với isLightTheme được đặt thành true hoặc chưa được đặt. WebView hiển thị nội dung ở giao diện sáng mà tác giả nội dung đã xác định. WebView hiển thị nội dung theo kiểu mặc định do tác giả nội dung xác định.
Ứng dụng đang dùng chế độ Buộc chế độ tối để áp dụng giao diện tối theo thuật toán cho ứng dụng. WebView hiển thị nội dung ở giao diện tối mà tác giả nội dung đã xác định. Nếu tác giả nội dung cho phép, WebView sẽ hiển thị nội dung bằng giao diện tối được tạo bằng thuật toán.
Ứng dụng đang dùng giao diện tối, trong đó isLightTheme được đặt thành false và ứng dụng không cho phép làm tối bằng thuật toán đối với WebView. WebView hiển thị nội dung ở giao diện tối mà tác giả nội dung đã xác định. WebView hiển thị nội dung theo kiểu mặc định do tác giả nội dung xác định.
Ứng dụng đang dùng giao diện tối với isLightTheme được đặt thành false và ứng dụng cho phép làm tối thuật toán cho WebView. WebView hiển thị nội dung ở giao diện tối mà tác giả nội dung đã xác định. Nếu tác giả nội dung cho phép, WebView sẽ hiển thị nội dung bằng giao diện tối được tạo bằng thuật toán.

Định kiểu cho tác giả nội dung

Thuộc tính isLightTheme của ứng dụng cho biết giao diện của ứng dụng là sáng hay tối. WebView luôn đặt prefers-color-scheme theo isLightTheme. Nếu isLightThemetrue hoặc không được chỉ định, thì prefers-color-scheme sẽ là light; nếu không, giá trị sẽ là dark.

Tức là nếu nội dung web sử dụng prefers-color-scheme và tác giả nội dung cho phép, thì giao diện sáng hoặc tối do tác giả nội dung xác định sẽ luôn tự động được áp dụng cho nội dung trên web sao cho phù hợp với giao diện của ứng dụng.

Làm tối bằng thuật toán

Để xử lý các trường hợp mà nội dung trên web không sử dụng prefers-color-scheme, ứng dụng của bạn có thể cho phép WebView (khi cần) áp dụng giao diện tối cho nội dung trên web mà nội dung đó hiển thị theo thuật toán.

Nếu ứng dụng của bạn đang dùng tính năng Buộc tối ở cấp ứng dụng để áp dụng giao diện tối theo thuật toán cho ứng dụng, hãy xem phần dưới đây mô tả cách cho phép thuật toán làm tối cho nội dung trên web bằng tính năng Buộc chế độ tối.

Nếu ứng dụng của bạn không dùng tính năng Buộc chế độ tối, thì cách ứng dụng chỉ định thời điểm cho phép làm tối thuật toán trong WebView sẽ tuỳ thuộc vào cấp độ API mục tiêu của ứng dụng. Hãy xem các phần sau đây về ứng dụng nhắm đến Android 13 trở lênứng dụng nhắm đến Android 12 trở xuống để biết thông tin chi tiết.

Cho phép phương thức làm tối bằng thuật toán đối với nội dung trên web bằng tính năng Buộc tối

Nếu ứng dụng của bạn đang dùng tính năng Buộc tối ở cấp ứng dụng, thì WebView sẽ áp dụng chế độ làm tối thuật toán cho nội dung trên web nếu đáp ứng các điều kiện sau:

  • WebView và các thành phần mẹ tương ứng đều cho phép tính năng Buộc chế độ tối.
  • Giao diện hoạt động hiện tại được đánh dấu là sáng khi isLightTheme được đặt thành true.
  • Tác giả nội dung trên web không tắt chế độ làm tối một cách rõ ràng.
  • Đối với ứng dụng nhắm đến Android 13 (API cấp 33) trở lên, nội dung web không sử dụng prefers-color-scheme.
  • Đối với ứng dụng nhắm đến Android 12 (API cấp 32) trở xuống: Ứng dụng đã đặt chế độ cài đặt forceDarkMode của WebView thành FORCE_DARK_AUTO và đã đặt chiến lược Buộc chế độ tối thành DARK_STRATEGY_USER_AGENT_DARKENING_ONLY.

WebView và tất cả các thành phần mẹ của WebView đều có thể cho phép chế độ tối ưu hoá bằng cách sử dụng View.setForceDarkAllowed(). Giá trị mặc định được lấy từ thuộc tính setForceDarkAllowed() của giao diện Android. Bạn cũng phải đặt giá trị này thành true.

Buộc chế độ tối được cung cấp chủ yếu cho khả năng tương thích ngược trong những ứng dụng không cung cấp giao diện tối riêng. Nếu ứng dụng của bạn dùng tính năng Buộc chế độ tối, thì bạn nên thêm khả năng hỗ trợ giao diện tối.

Cho phép làm tối bằng thuật toán (ứng dụng nhắm đến Android 13 trở lên)

Đối với các ứng dụng không dùng tính năng Buộc chế độ tối ở cấp ứng dụng và nhắm đến Android 13 (API cấp 33) trở lên, hãy sử dụng phương thức AndroidX setAlgorithmicDarkeningAllowed() và truyền vào true để chỉ định rằng WebView sẽ cho phép làm tối theo thuật toán. Phương thức này có khả năng tương thích ngược với các phiên bản Android trước.

Sau đó, WebView sẽ áp dụng chế độ làm tối bằng thuật toán nếu đáp ứng các điều kiện sau:

  • Nội dung trên web không sử dụng prefers-color-scheme.
  • Tác giả nội dung trên web không tắt chế độ làm tối một cách rõ ràng.

Cho phép làm tối bằng thuật toán (ứng dụng nhắm đến Android 12 trở xuống)

Đối với các ứng dụng không dùng tính năng Buộc chế độ tối ở cấp ứng dụng và nhắm đến Android 12 (API cấp 32) trở xuống, hãy dùng FORCE_DARK_ON để cho phép phương thức làm tối bằng thuật toán.

Sử dụng FORCE_DARK_ON cùng với FORCE_DARK_OFF nếu ứng dụng của bạn cung cấp phương thức riêng để chuyển đổi giữa giao diện sáng và tối, chẳng hạn như một phần tử có thể bật/tắt trong giao diện người dùng hoặc lựa chọn tự động dựa trên thời gian.

Để kiểm tra xem tính năng này có được hỗ trợ hay không, hãy thêm các dòng mã sau ở bất cứ nơi nào bạn định cấu hình đối tượng WebView, chẳng hạn như trong Activity.onCreate:

Kotlin

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(...)
}

Java

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    WebSettingsCompat.setForceDark(...);
}

Nếu ứng dụng của bạn dựa vào việc phát hiện các thay đổi đối với lựa chọn ưu tiên của hệ thống, thì ứng dụng phải theo dõi rõ ràng các thay đổi về giao diện và áp dụng các thay đổi đó cho WebView với các trạng thái FORCE_DARK_ONFORCE_DARK_OFF.

Đoạn mã sau đây cho biết cách thay đổi định dạng giao diện:

Kotlin

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
        Configuration.UI_MODE_NIGHT_YES -> {
            WebSettingsCompat.setForceDark(myWebView.settings, FORCE_DARK_ON)
        }
        Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_UNDEFINED -> {
            WebSettingsCompat.setForceDark(myWebView.settings, FORCE_DARK_OFF)
        }
        else -> {
            //
        }
    }
}

Java

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) {
    switch (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
        case Configuration.UI_MODE_NIGHT_YES:
            WebSettingsCompat.setForceDark(myWebView.getSettings(), FORCE_DARK_ON);
            break;
        case Configuration.UI_MODE_NIGHT_NO:
        case Configuration.UI_MODE_NIGHT_UNDEFINED:
            WebSettingsCompat.setForceDark(myWebView.getSettings(), FORCE_DARK_OFF);
            break;
    }
}

Tuỳ chỉnh cách xử lý giao diện tối

Bạn cũng có thể dùng ForceDarkStrategy API trong AndroidX để kiểm soát cách áp dụng chế độ làm tối cho một WebView nhất định. API này chỉ áp dụng nếu chế độ buộc tối được đặt thành FORCE_DARK_ON hoặc FORCE_DARK_AUTO.

Khi sử dụng API này, ứng dụng của bạn có thể dùng chế độ làm tối giao diện web hoặc làm tối tác nhân người dùng:

  • Làm tối giao diện web: Nhà phát triển web có thể áp dụng @media (prefers-color-scheme: dark) để kiểm soát giao diện của trang web ở chế độ tối. WebView hiển thị nội dung theo các chế độ cài đặt này. Để biết thêm thông tin về cách làm tối giao diện web, hãy xem thông số kỹ thuật.
  • Làm tối tác nhân người dùng: WebView tự động đảo ngược màu của trang. Nếu bạn sử dụng tính năng làm tối tác nhân người dùng, truy vấn @media (prefers-color-scheme: dark) sẽ có giá trị là false.

Để chọn một trong hai chiến lược này, hãy sử dụng API sau:

Kotlin

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)) {
    WebSettingsCompat.setForceDarkStrategy(...)
}

Java

if (WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY)) {
    WebSettingsCompat.setForceDarkStrategy(...);
}

Các chiến lược được hỗ trợ bao gồm:

  • DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING: Đây là tuỳ chọn mặc định. Mặc dù hầu hết các trình duyệt đều coi thẻ <meta name="color-scheme" content="dark light"> là không bắt buộc, nhưng chế độ mặc định của Android WebView yêu cầu thẻ meta để đáp ứng truy vấn phương tiện prefers-color-scheme của trang web. Bạn có thể sử dụng WebView với chế độ DARK_STRATEGY_WEB_THEME_DARKENING_ONLY. Trong trường hợp đó, WebView luôn áp dụng các truy vấn nội dung đa phương tiện ngay cả khi thẻ bị bỏ qua.

    Tuy nhiên, các nhà phát triển web nên thêm thẻ <meta name="color-scheme" content="dark light"> vào trang web của họ để đảm bảo nội dung hiển thị chính xác trong WebView với cấu hình mặc định.

  • DARK_STRATEGY_USER_AGENT_DARKENING_ONLY: Được gọi là "làm tối tác nhân người dùng", WebView sẽ bỏ qua mọi chế độ làm tối của trang web và áp dụng chế độ làm tối tự động.

Nếu ứng dụng của bạn hiển thị nội dung trên web của bên thứ nhất mà bạn đã tuỳ chỉnh bằng truy vấn nội dung nghe nhìn prefers-color-scheme, thì bạn nên sử dụng DARK_STRATEGY_WEB_THEME_DARKENING_ONLY để đảm bảo WebView sử dụng giao diện tuỳ chỉnh.

Để xem ví dụ về giao diện tối được áp dụng, hãy xem bản minh hoạ WebView trên GitHub