LoginSignup
1
1

Accompanist の WebView Wrapper メモ1: `window.confirm` がそのままで表示される

Last updated at Posted at 2023-06-26

Accompanist の WebView Wrapper を使って
Jetpack Compose で WebView を使うときのメモです。

👇 次の回

このときのバージョンは com.google.accompanist:accompanist-webview:0.30.1 です。

JS の window.confirm がなにもせず表示されてる

Android View の WebView だと JavaScript の window.confirm といったダイアログについて、
自分で WebChromeClient を指定しないと表示してくれなかったのですが、
Accompanist の WebView Wrapper だとデフォルトで表示するようになっていることに気づきました:

MyWebView.kt
@SuppressLint("SetJavaScriptEnabled")
@Composable
private fun MyWebView(
    modifier: Modifier = Modifier,
) {
    val state = rememberWebViewState(
        url = "https://codepen.io/mangano_ito/pen/jOeZKxP",
    )
    WebView(
        state = state,
        onCreated = { webView ->
            webView.settings.javaScriptEnabled = true
            webView.settings.domStorageEnabled = true
        },
        modifier = modifier,
    )
}

window.confirm テスト

テストに使ったページはこれのために用意した
ホントに window.confirm だけする CodePen のページです:

なぜ表示される?

これは Accompanist だとデフォルト実装の WebChromeClient を与えてくれるようになっているからです:

accompanist/web/src/main/java/com/google/accompanist/web/WebView.kt (LL.73-84)
@Composable
fun WebView(
    state: WebViewState,
    modifier: Modifier = Modifier,
    captureBackPresses: Boolean = true,
    navigator: WebViewNavigator = rememberWebViewNavigator(),
    onCreated: (WebView) -> Unit = {},
    onDispose: (WebView) -> Unit = {},
    client: AccompanistWebViewClient = remember { AccompanistWebViewClient() },
    chromeClient: AccompanistWebChromeClient = remember { AccompanistWebChromeClient() },
    factory: ((Context) -> WebView)? = null
) {

accompanist/web/src/main/java/com/google/accompanist/web/WebView.kt(LL.148-160)
        AndroidView(
            factory = { context ->
                val childView = (factory?.invoke(context) ?: WebView(context)).apply {
                    onCreated(this)

                    layoutParams = LayoutParams(
                        width,
                        height
                    )

                    webChromeClient = chromeClient
                    webViewClient = client
                }.also { webView = it }

なぜ Android View ではデフォルトで表示されなかった?

WebChromeClientonJsConfirm の説明にあるように、
指定しなければ confirm は抑止されるようになっているからです:

Note that if the WebChromeClient is set to be null, or if WebChromeClient is not set at all, the default dialog will be suppressed and the default value of false will be returned to the JavaScript code immediately.

なので Android View ではデフォルトではなにも指定されずダイアログが表示されないので、
自分で指定してあげないといけなかったという話題がありました:

(↑ 先駆者のかたの記事)

したがって、こういう違いにより動作が変わっています:

AndroidViewWebView.kt
binding.webview.apply {
    settings.javaScriptEnabled = true
    settings.domStorageEnabled = true
    // ↓ これが ない または `null` のときは表示されない
    webChromeClient = WebChromeClient()
    loadUrl("https://codepen.io/mangano_ito/pen/jOeZKxP")
}
未指定 or null 指定
android-view-webview-unspecified.gif android-view-webview-specified.gif

おわりです

AndroidView を使わず Accompanist の WebView Wrapper を使う場合はとくに意識せずこれが有効になっているので後でアレっとはなりづらいですね。地味な違い。

以上です。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1