퉁탕퉁탕 만들어보자

Android WebView에 Darkmode 적용하기 본문

Computer/Android

Android WebView에 Darkmode 적용하기

호숀티 2021. 6. 28. 23:04
반응형

Android webview에 darkmode 적용은 Q이상부터 가능하다. 

13이상 (API 33) 부터는 동작이 변경되어 맨 아래에 따로 기술한다. (매우 간단해짐!)

 

Target SDK 33 이전

webview를 dark하게 만드는 방법은 2가지가 있다. 

1) User Agent(browser) 가 강제로 dark하게 만드는법

2) 웹 페이지에서 CSS를 통해 dark 테마를 적용하는 법

 

1. WebView에 setForceDark를 해준다.

WebSettingsCompat.setForceDark(...)

* 업데이트! Android 13(API 수준 33) 이상을 타겟팅하는 앱의 경우 setForceDark() 메서드가 지원 중단되므로 이 메서드가 호출되면 작동하지 않음!

 

우선 1)번과 2)번 둘다 필요한 내용을 적용해본다.

해당 작업은 onCreate에서 해줘도 되고, AndroidManifest에서 configChanges에 uiMode를 선언했다면

onConfigurationChanged에서 해줘도 된다.

이렇게 하지 않으면, 웹에서 @media (prefers-color-scheme: dark)를 구현을 해놨더라도 dark mode적용이 안된다.

when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
    Configuration.UI_MODE_NIGHT_YES -> {
        //enable force dark
    }
    Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_UNDEFINED -> {
        //disable force dark
    }
    else -> {
        //
    }
}


2. 다크모드 strategy 설정하기

WebSettingsCompat.setForceDarkStrategy(...)

 


이제 strategy를 설정해주려면, 새로운 디펜던시를 build.gradle에 걸어줘야 한다.

androidx.webkit:webkit:1.3.0

 

Webkit  |  Android 개발자  |  Android Developers

Webkit Android 5 이상에서 최신 WebView API로 작업합니다. 최근 업데이트 현재 안정화 버전 다음 버전 후보 베타 버전 알파 버전 2020년 12월 16일 1.4.0 - - - 종속 항목 선언 Webkit의 종속 항목을 추가하려

developer.android.com

setForceDarkStrategy는 안드로이드 시스템웹뷰 v83부터 지원된다. 

 

strategy에는 3가지 종류가 있다.

- DARK_STRATEGY_PREFER_WEB_THEME_OVER_USER_AGENT_DARKENING (줄여서 웹 테마 over UA)

- DARK_STRATEGY_WEB_THEME_DARKENING_ONLY (웹 테마 ONLY)

- DARK_STRATEGY_UA_DARKENING_ONLY (UA ONLY)

 

v76~ 에서는 setForceDark했을 때 웹 테마 ONLY 로 설정되어서 변경불가능하고,

v83부터는 WEB_THEME_OVER_USER_AGENT_DARKENING 이 default 이고, setForceDarkStrategy 로 변경가능하다.

 

이 모드가 무엇인고 하니, 웹 페이지 소스에 메타데이터에 color-scheme이 있으면 ( <meta name="color-scheme" content="dark light">" 이렇게) , Android WebView가 prefer-color-scheme 미디어 쿼리를 처리하게 된다. 그런데, color-scheme이 없으면 ? User Agent 가 강제로 알아서 색을 정해준다.

이걸 방지하고 싶으면, 웹 테마 ONLY 로 strategy를 바꿔주면 된다.

 

이 옵션이 좀 안전한게, webkit에서 나름 잘 바꿔줘도 검정색 로고 같은건 검은 바탕때문에 안보이게 되는경우가 있다.

그래서 웹 개발자에게 dark mode 구현을 일임하고,  웹 테마 다크닝 ONLY로 가는게 좋다.

 

두가지 케이스가 있을 것 같다.

하나) 앱 내의 웹뷰에서만 열릴 페이지인 경우 (웹앱 같은거)

 이럴때는 Q이하의 디바이스에서도 지원하기 위해서 여태까지 말한것을 무시하고 js interface로 직접 darkmode인지 set해주는 함수를 만들어서 직접 테마를 적용해도 된다.

둘) 다른 브라우저에서도 열릴 페이지인 경우

CSS를 구현해서 prefer-color-scheme을 잘 구현해서 다른 브라우저에서도 sbrowser, whale, chrome등에서도 같이 dark테마를 적용할 수 있다면 일관된 사용성을 느낄수 있으므로 css 다크모드 구현에 투자할만하다.

 

세번째 옵션은 DARK_STRATEGY_USER_AGENT_DARKENING_ONLY 로, web page의 dark theme 옵션 다 무시하고 

UA가 알아서 darkening을 하겠다는 옵션이다. 선택할 일이 잘 없을 것 같다.

 

 

3. 당신의 앱은 소중하니까 API를 콜하기 전에 feature 체크를 해주자

피쳐 체크를 하기 위해서는 아까 2. 에서 물었던 webkit:1.3.0 이 필요하다.

 

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

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

 

이렇게 해주자. 왜냐면 클라이언트에 깔려있는 시스템 웹뷰가 구버전인 경우 exception이 나서 죽게된다. catch 해줘도 될것 같은데 실제로 테스트는 안해봤다. v76이면 좀 오래되긴 했다.

 

4. 그럼 웹에서는 어떻게 하면 될까?

아래의 글을 참고해보면 될것이다.

크게는 metadata 에 추가, media query 구현 이렇게 2가지의 할일이 있다.

https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme

 

prefers-color-scheme - CSS: Cascading Style Sheets | MDN

The prefers-color-scheme CSS media feature is used to detect if the user has requested a light or dark color theme.

developer.mozilla.org

https://css-tricks.com/a-complete-guide-to-dark-mode-on-the-web/

 

A Complete Guide to Dark Mode on the Web

“Dark mode” is defined as a color scheme that uses light-colored text and other UI elements on a dark-colored background. Dark mode, dark theme, black mode, night mode… they all refer to and mean the same thing: a mostly-dark interface rather than a

css-tricks.com


targetSDK 33 이상!!

앱 색상 테마가 WebView 콘텐츠에 자동으로 적용됨

Android 13(API 수준 33) 이상을 타겟팅하는 앱의 경우 

* setForceDark() 메서드가 지원 중단되므로 이 메서드가 호출되면 작동하지 않음.

* WebView가 앱의 테마 속성 isLightTheme에 따라 미디어 쿼리 prefers-color-scheme을 항상 설정

     * 즉, isLightTheme이 true이거나 지정되지 않은 경우 prefers-color-scheme은 light, 그 외의 경우에는 dark

기존처럼 onConfigurationChanged 에서 직접 dark, light 를 구분해서 setForceDark() 함수 호출이 필요없어진다는 의미임!

 

이전 Android 버전과의 호환성을 위해 AndroidX에서 동등한 setAlgorithmicDarkeningAllowed() 메서드를 사용하라고 

Developer 사이트에서는 권장을 하고 있다.

아래는 설정값에 따른 웹뷰 화면 theme 이다.

App prefers-color-scheme
을 사용하는 Web content
prefers-color-scheme
을 사용하지 않는 Web content
isLightTheme True 또는 not set content author가 정의한 light theme 으로 그려짐 content author 가 정의한 default style 로 그려짐
Android forceDark in effect content author가 정의한 dark theme 으로 그려짐 content author가 허용한다면, 알고리즘이 알아서 계산한 dark color 로 그려짐
isLightTheme False &&
targetSdkVersion < Build.VERSION_CODES.TIRAMIS &&
FORCE_DARK_AUTO
content author가 정의한 dark theme 으로 그려짐 content author 가 정의한 default style 로 그려짐
isLightTheme False &&
targetSdkVersion  Build.VERSION_CODES.TIRAMISU &&
setAlgorithmicDarkening(false)
content author가 정의한 dark theme 으로 그려짐 content author 가 정의한 default style 로 그려짐
isLightTheme False &&
targetSdkVersion  Build.VERSION_CODES.TIRAMISU &&
setAlgorithmicDarkening(true)
content author가 정의한 dark theme 으로 그려짐 content author가 허용한다면, 알고리즘이 알아서 계산한 dark color 로 그려짐


참고

https://developer.android.com/guide/webapps/dark-theme#kotlin

728x90
반응형