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

Trên Android 10 trở lên, ứng dụng có thể hỗ trợ Giao diện tối và tự động thay đổi giữa giao diện sáng và tối của ứng dụng theo giao diện của hệ thống. Để khớ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. Khi có thể, nếu tác giả nội dung 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 và triển khai prefers-color-scheme để WebView có thể khớp 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 web trong ứng dụng, tuỳ thuộc vào kiểu của nội dung web và điều kiện của ứng dụng:

Đ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 dùng giao diện sáng có isLightTheme được đặt thành true hoặc chưa được đặt. WebView hiển thị nội dung bằng giao diện sáng mà tác giả nội dung đã xác định. WebView hiển thị nội dung bằng kiểu mặc định do tác giả nội dung xác định.
Ứng dụng đang sử dụng tính năng 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 bằng 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 một giao diện tối có isLightTheme được đặt thành false và ứng dụng này không cho phép chế độ làm tối theo thuật toán đối với WebView. WebView hiển thị nội dung bằng giao diện tối mà tác giả nội dung đã xác định. WebView hiển thị nội dung với kiểu mặc định do tác giả nội dung xác định.
Ứng dụng đang sử 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 theo thuật toán cho WebView. WebView hiển thị nội dung bằng 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 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ị này sẽ là dark.

Tức là nếu nội dung trên 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 áp dụng cho nội dung trên web để 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 nội dung 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 thiết) áp dụng thuật toán một giao diện tối cho nội dung web mà ứng dụng hiển thị.

Nếu ứng dụng của bạn đang dùng tính năng Buộc chế độ tối ở cấp ứng dụng để áp dụng giao diện tối cho ứng dụng bằng thuật toán, hãy xem phần sau đây mô tả cách bật tính năng làm tối bằng thuật toán 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 dựa trên thuật toán trong WebView phụ 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 làm tối nội dung web bằng thuật toán với tính năng Buộc chế độ tối

Nếu ứng dụng của bạn đang dùng tính năng Buộc làm tối ở cấp ứng dụng, thì WebView sẽ áp dụng tính năng làm tối theo 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 phần tử mẹ của WebView cho phép chế độ Buộc chế độ tối.
  • Giao diện hoạt động hiện tại được đánh dấu là sáng với isLightTheme được đặt thành true.
  • Tác giả nội dung web không tắt chế độ làm tối một cách rõ ràng.
  • Đối với các ứ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ả thành phần mẹ của nó có thể cho phép chế độ buộc chế độ tối 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, thuộc tính này cũng phải được đặt thành true.

Chế độ Buộc tối được cung cấp chủ yếu để tương thích ngược trong các ứng dụng không cung cấp giao diện tối riêng. Nếu ứng dụng của bạn sử dụng tính năng Buộc chế độ tối, bạn nên thêm tính 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 sử 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 setAlgorithmicDarkeningAllowed() của AndroidX và truyền vào true để chỉ định rằng WebView phải 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 theo thuật toán nếu đáp ứng các điều kiện sau:

  • Nội dung web không sử dụng prefers-color-scheme.
  • Tác giả nội dung 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 ứ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 sử dụng FORCE_DARK_ON để cho phép làm tối theo 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ử bật/tắt được trong giao diện người dùng hoặc lựa chọn tự động theo 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 vào 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 về 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 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ể sử 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 bạn đặt tính năng buộc tối 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ể sử dụng tính năng 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 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 về tính năng 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 sắc của trang web. Nếu bạn sử dụng tính năng làm tối tác nhân người dùng, thì truy vấn @media (prefers-color-scheme: dark) sẽ đánh giá thành false.

Để chọn giữa 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à lựa chọn mặc định. Mặc dù hầu hết trình duyệt đều không bắt buộc phải dùng thẻ <meta name="color-scheme" content="dark light">, nhưng chế độ mặc định của Android WebView lại yêu cầu thẻ meta để tuân thủ các truy vấn nội dung nghe nhì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 này, WebView luôn áp dụng truy vấn nội dung đa phương tiện ngay cả khi bạn bỏ qua thẻ.

    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 mình để đả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 user-agent", WebView bỏ qua mọi chế độ làm tối 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 web của bên thứ nhất mà bạn đã tuỳ chỉnh bằng truy vấn nội dung đa phương tiện prefers-color-scheme, bạn nên DARK_STRATEGY_WEB_THEME_DARKENING_ONLY để đảm bảo WebView sử dụng giao diện tuỳ chỉnh.

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