SwipeRefresh fails to detect gestures when Webview is used with SwipeRefresh
日付:2022/08/31
URL:https://github.com/google/accompanist/issues/1235
調査者:Mori Atsushi
カテゴリ:Jetpack Compose
一言で表すと
WebViewがComposeのNested Scrollに対応してないので、pull to refreshやcollapsed app barが動かない
概要
acccompanistには SwipeRefresh と WebView が用意されている
SwipeRefreshでWebViewを囲っても動かない
下にスワイプしてもSwipeRefreshは出ない
code:kotlin
val swipeRefreshState = rememberSwipeRefreshState()
var webView: WebView? by remember { mutableStateOf(null) }
SwipeRefresh(
state = swipeRefreshState,
onRefresh = {
swipeRefreshState.isRefreshing = true
webView?.reload()
swipeRefreshState.isRefreshing = false
}
) {
WebView(
state = webViewState,
onCreated = {
webView = it
}
)
}
PR①:android viewのswipe refreshを使う
https://github.com/google/accompanist/pull/1242
code:kotlin
@Composable
fun SwipeRefreshWebView(
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() },
swipeRefreshState: SwipeRefreshState,
swipeEnabled: Boolean = true,
onRefresh: () -> Unit = {},
) {
mergeされずclose
バグを回避するためにAPI追加はできない
適切な修正は、Accompanist SwipeToRefresh を Accompanist WebView で動作させること
必要な場合は、この方法が利用できる
Mori Atsushi.icon それはそう
PR②:NestedScroll Viewでwebviewを囲う
https://github.com/google/accompanist/pull/1270
code:kotlin
val web = WebView(context).apply {
onCreated(this)
/* ... */
}
NestedScrollView(context).apply {
addView(web)
}
mergeされずclose
奇妙なスクロールが発生する
https://user-images.githubusercontent.com/4217560/184943172-22526e5b-5b7d-4d71-9dd8-5d57c2f3e790.mp4
ネスト スクロールの相互運用(試験運用版)
https://developer.android.com/jetpack/compose/gestures?hl=ja#nested-scrolling-interop
子 AndroidView を含んでいる親コンポーザブルの場合
Android Viewは NestedScrollingChild3 を implementしておけば良いっぽい
Mori Atsushi.icon 3という名前に歴史を感じる
RyuNen344.icon androidの軽率にバージョン数上げていくやつ好き
NestedScrollingChild3を実装するためには?
code:kotlin
override fun onTouchEvent(event: MotionEvent): Boolean {
when (actionMasked) {
MotionEvent.ACTION_DOWN -> {
/* ... */
}
MotionEvent.ACTION_MOVE -> {
// ①親要素にスクロールイベントを渡し、場合によってはスクロール量を消費する
dispatchNestedPreScroll(/* ... */)
// ②残ったスクロール量だけ自身のスクロール
scroll(/* ... */ )
// ③さらに残ったスクロールを親に渡す
dispatchNestedScroll(/* ... */ )
/* ... */
スクロール量の制御、消費されるスクロール量の検知が必要
過去の実装例
https://github.com/takahirom/webview-in-coordinatorlayout/blob/master/app/src/main/java/com/github/takahirom/webview_in_coodinator_layout/NestedWebView.java
coordinatorlayout内でwebviewを動かすための実装
webviewでNestedScrollingChildを実装している
NestedScrollingChildやNestedScrollingChildは呼んでるが、消費を正しく検知してないのでswipe refreshは動かない
https://github.com/hellowwwwp/WebViewDemo/blob/master/webview/src/main/java/com/hellowwwwp/webview/NestedScrollWebView.kt
OverScrollerを使ってスクロールを再実装している
これを使うと概ね正しく動く
一番外側をスクロールしてるだけなので、webview内にネストスクロールがあると動かない
google mapとか、カルーセルとか
気になるポイント
メモ
コメント