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 chuyển đổi giữa 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 hiện tại của ứng dụng, nội dung web trong WebView cũng có thể sử dụng kiểu sáng, tối hoặc kiểu mặc định.

Hành vi của WebView tương tác với các prefers-color-schemecolor-scheme tiêu chuẩn web. Khi có thể, nếu bạn tạo 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 kết xuất nội dung 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:

Điều kiện của ứ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 không được đặt. WebView kết xuất nội dung bằng giao diện sáng mà tác giả nội dung đã xác định. WebView kết xuất 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 Bật nhanh giao diện tối để áp dụng giao diện tối cho ứng dụng theo thuật toán. WebView kết xuất nội dung bằng giao diện tối mà tác giả nội dung đã xác định. Nếu được tác giả nội dung cho phép, WebView sẽ kết xuất nội dung bằng giao diện tối được tạo bằng thuật toán.
Ứng dụng đang sử dụng giao diện tối với isLightTheme được đặt thành false và ứng dụng không cho phép làm tối theo thuật toán cho WebView. WebView kết xuất nội dung bằng giao diện tối mà tác giả nội dung đã xác định. WebView kết xuất 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 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 kết xuất nội dung bằng giao diện tối mà tác giả nội dung đã xác định. Nếu được tác giả nội dung cho phép, WebView sẽ kết xuất nội dung bằng giao diện tối được tạo bằng thuật toán.

Kiểu của 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-schemelight; nếu không, thì là dark.

Điều này có nghĩa 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 được tự động áp dụng cho nội dung web để phù hợp với giao diện của ứng dụng.

Làm tối theo 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 giao diện tối cho nội dung web mà ứng dụng kết xuất theo thuật toán.

Nếu ứng dụng của bạn đang sử dụng tính năng Bật nhanh giao diện tối ở cấp ứng dụng để áp dụng Giao diện tối cho ứng dụng theo thuật toán, hãy xem phần sau đây mô tả cách cho phép làm tối theo thuật toán cho nội dung trên web bằng tính năng Bật nhanh giao diện tối.

Nếu ứng dụng của bạn không sử dụng tính năng Bật nhanh giao diện tối, thì cách ứng dụng chỉ định thời điểm cho phép làm tối theo thuật toán trong WebView sẽ 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 để biết thông tin chi tiết về các ứng dụng nhắm đến Android 13 trở lêncác ứng dụng nhắm đến Android 12 trở xuống.

Cho phép làm tối theo thuật toán cho nội dung trên web bằng tính năng Bật nhanh giao diện tối

Nếu ứng dụng của bạn đang sử dụng tính năng Bật nhanh giao diện 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 web nếu các điều kiện sau được đáp ứng:

  • WebView và các phần tử mẹ của WebView cho phép tính năng Bật nhanh giao diện 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 tính năng làm tối một cách rõ ràng.
  • Đối với các ứng dụng nhắm đến Android 13 (cấp độ API 33) trở lên, nội dung trên web không sử dụng prefers-color-scheme.
  • Đối với các ứng dụng nhắm đến Android 12 (cấp độ API 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 Bật nhanh giao diện tối thành DARK_STRATEGY_USER_AGENT_DARKENING_ONLY.

WebView và tất cả các phần tử mẹ của WebView có thể cho phép buộc giao diện 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.

Bật nhanh giao diện 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 Bật nhanh giao diện 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 theo thuật toán (các ứ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 Bật nhanh giao diện tối ở cấp ứng dụng và nhắm đến Android 13 (cấp độ API 33) trở lên, hãy sử dụng phương thức setAlgorithmicDarkeningAllowed() của Jetpack Webkit và truyền 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 tương thích ngược với các phiên bản Android trước.

Sau đó, WebView sẽ áp dụng tính năng làm tối theo thuật toán nếu các điều kiện sau được đáp ứng:

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

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

Đối với các ứng dụng không sử dụng tính năng Bật nhanh giao diện tối ở cấp ứng dụng và nhắm đến Android 12 (cấp độ API 32) trở xuống, hãy sử dụng FORCE_DARK_ON để cho phép làm tối theo thuật toán.

Hãy 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 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 tuỳ chọn ưu tiên của hệ thống, thì ứng dụng đó phải nghe rõ các thay đổi về giao diện và áp dụng các thay đổi này 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ể sử dụng ForceDarkStrategy API trong thư viện Jetpack để kiểm soát cách áp dụng tính năng làm tối cho một WebView nhất định. API này chỉ áp dụng nếu tính năng buộc giao diện 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ể sử dụng tính năng làm tối giao diện web hoặc tính năng 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 kết xuất 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 của trang web page. 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, 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 tuỳ chọn chiến lược được hỗ trợ là:

  • 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's yêu cầu thẻ meta phải tuân theo các truy vấn phương tiện prefers-color-scheme của trang web. Bạn có thể sử dụng WebView ở chế độ DARK_STRATEGY_WEB_THEME_DARKENING_ONLY . Trong trường hợp này, WebView luôn áp dụng các truy vấn phương tiện ngay cả khi thẻ bị bỏ qua.

    Tuy nhiên, nhà phát triển web nên thêm <meta name="color-scheme" content="dark light"> thẻ vào trang web của họ để đảm bảo rằng nội dung kết xuất chính xác trong WebView có 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 bỏ qua mọi tính năng làm tối trang web và áp dụng tính năng làm tối tự động.

Nếu ứng dụng của bạn hiển thị nội dung web bên thứ nhất mà bạn đã tuỳ chỉnh bằng truy vấn phương tiện prefers-color-scheme, 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ụ áp dụng giao diện tối, hãy xem bản minh hoạ WebView trên GitHub