Accompanist の WebView Wrapper を使って
Jetpack Compose で WebView を使うときのメモです。
👇 前回
このときのバージョンは com.google.accompanist:accompanist-webview:0.30.1
です。
今回のケースのサンプルコード
Google を WebView で表示する最小限のコードを書いてみます:
@Composable
private fun MyWebViewTest() {
MyWebView(
url = "https://www.google.co.jp/",
)
}
@SuppressLint("SetJavaScriptEnabled")
@Composable
private fun MyWebView(
url: String,
modifier: Modifier = Modifier,
) {
val state = rememberWebViewState(url = url)
WebView(
state = state,
onCreated = { webView ->
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
},
modifier = modifier,
)
}
状態は安定版では画面回転に生き残らない
ページのナビゲーションの履歴や WebViewState
が保持するページのタイトル, URL などの状態は画面回転を生き残りません:
そのままだと状態が失われるのは
他の Jetpack Compose で使われる種々の State でも同じ話題がありますが、
WebView だと結構予想を裏切る感じで違和感があるかもしれません。
どうすればいいの?
今の安定版では rememberSaveable
な API は用意されていないので、
必要な状態は onCreated
, onDispose
時に自分で保持する必要があるということを意味しています。
これに関しては Issue が立てられていまして、ここで Workaround がコメントされていたりします:
そしてつい最近 v0.31.1-alpha
で対応がされていて、
Saver
が指定された rememberSaveableWebViewState
という関数が追加されています:
+import androidx.compose.runtime.LaunchedEffect
-import com.google.accompanist.web.rememberWebViewState
+import com.google.accompanist.web.rememberSaveableWebViewState
+import com.google.accompanist.web.rememberWebViewNavigator
// 略…
- val state = rememberWebViewState(url = url)
+ val state = rememberSaveableWebViewState()
+ val navigator = rememberWebViewNavigator()
+ LaunchedEffect(navigator) {
+ val bundle = state.viewState
+ if (bundle == null) {
+ navigator.loadUrl(url)
+ }
+ }
WebView(
state = state,
+ navigator = navigator,
onCreated = { webView ->
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
以前の状態がなければロードすることになるので、
LaunchedEffect
で WebViewState.viewState
が null
か確認して WebViewNavigator#loadUrl
をすることになるのがポイントですね。
これで画面回転しても状態が生き残るので違和感がない感じにできました:
まだ安定版ではないですが、必要に応じてこれを使うことになるでしょう。
(Bundle
の容量の話題はありつつ)
以上です。