WebView 嵌套滚动在 Android Jetpack Compose 中不起作用

问题描述 投票:0回答:5

WebView 不在 Compose 内滚动。 我需要使用 Compose 将 WebView 放入 BottomSheet 中。即使我们使用例如 WebView 也不会滚动的问题NestedWebView,或NestedScrollWebView。 如果我将 WebView 放入 NestedScrollView 中,它仍然不会对滚动做出反应。

BottomSheetScaffold(
        sheetContent = {
            AndroidView(factory = {
                NestedWebView(it).apply {
                        layoutParams = ViewGroup.LayoutParams(
                            ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.MATCH_PARENT
                        )
                        settings.domStorageEnabled = true
                        settings.javaScriptEnabled = true
                        settings.useWideViewPort = true
                        webViewClient = WebViewClient()
                        //loadUrl("https://contest.rippl.club/")
                        loadUrl("https://codeflarelimited.com")
                    }
                })

        }) {
    }

解决方法之一是使用verticalScroll并将webview高度设置为WRAP_CONTENT:

 val scrollState = rememberScrollState()
 AndroidView(modifier = Modifier.verticalScroll(scrollState), factory = {
            WebView(it).apply {
                     layoutParams = ViewGroup.LayoutParams(
                          ViewGroup.LayoutParams.MATCH_PARENT,
                          ViewGroup.LayoutParams.WRAP_CONTENT
                          ---//---

但是有很多网站不能使用wrap_content,例如因为像这个网站这样的内部滚动https://contest.rippl.club/。该网站不适用于该解决方法。如果我们将webview高度设置为屏幕高度,它仍然不起作用,因为verticalScroll就像ScrollView一样,所以它只会滚动到这个高度。

我还检查了这个文档https://developer.android.com/jetpack/compose/gestures#parent-compose-child-view,但对于 webview 情况没有任何作用。

android webview android-jetpack-compose bottom-sheet
5个回答
1
投票

您需要使用

NestedScrollConnection
对象,并将其传递给外部视图上的nestedSCroll 修饰符。 这是一个基本示例


1
投票

这是一个小示例代码,它至少使 WebView 可以滚动:

private class MyWebView(context: Context) : WebView(context) {
    val verticalScrollRange: Int get() = computeVerticalScrollRange() - height
}

@Composable
fun WebViewCompose(url: String, modifier: Modifier = Modifier, onCreated: (WebView) -> Unit = {}) {
    val context = LocalContext.current
    val webView: MyWebView = remember(context) {
        MyWebView(context).also(onCreated)
    }
    DisposableEffect(webView) {
        onDispose {
            webView.stopLoading()
            webView.destroy()
        }
    }
    val scrollabeState = rememberScrollableState { delta ->
        val scrollY = webView.scrollY
        val consume = (scrollY - delta).coerceIn(0f, webView.verticalScrollRange.toFloat())
        webView.scrollTo(0, consume.roundToInt())
        (scrollY - webView.scrollY).toFloat()
    }
    AndroidView(
        factory = { webView },
        modifier = modifier
            .scrollable(scrollabeState, Orientation.Vertical)
    ) { webView2 ->
        webView2.loadUrl(url)
    }
}

1
投票

这个答案有帮助:https://stackoverflow.com/a/70195667/4256193

它对我有用:

Surface(
    modifier = Modifier.nestedScroll(rememberNestedScrollInteropConnection())
) {
    WebView(
        state = state,
        modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()),
        onCreated = { }
    )
}

0
投票

有一种简单的方法可以解决这个问题。我有一个和你一模一样的案例。 您需要做的就是像这样实现

pointerInput

AndroidView(
        modifier = Modifier
            .fillMaxHeight(0.9f)
            .pointerInput(Unit) {
                detectVerticalDragGestures { _, dragAmount ->
                    val initialDrag = currentVerticalDrag.value + dragAmount
                    val calculatedDrag = when {
                        initialDrag > 0 -> {
                            0
                        }
                        abs(initialDrag) > measuredHeight.value -> {
                            measuredHeight.value
                        }
                        else -> {
                            initialDrag.roundToInt()
                        }
                    }
                    currentVerticalDrag.value = calculatedDrag
                }
            },
        factory = {
            WebView(it).apply {
                settings.javaScriptEnabled = true
                addJavascriptInterface(jsInterface, "HTMLOUT")
                webViewClient = FaqWebViewClient(
                    onPageLoadingStart = {
                        isPageLoading.value = true
                    },
                    onPageLoadComplete = {
                        isPageLoading.value = false
                    }
                )
                loadUrl(url)
            }
        }, update = { webView ->
            webView.scrollTo(0, abs(currentVerticalDrag.value))
        }
    )

0
投票

我正在使用脚手架,在内容中添加一个带有verticalScroll(rememberScrollState())的列。我测试了几个网站并且在我的案例中有效。

Scaffold(
    topBar = {
        // Your Top bar with e.g url, navigation etc
    },
    content = { pv ->
        Column(
            modifier = Modifier
                .padding(pv)
                .fillMaxSize()
                .verticalScroll(rememberScrollState())
        ) {
            AndroidView(factory = {
                WebView(it).apply {
                    layoutParams = ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT
                    )
                    webViewClient = WebViewClient()
                    settings.javaScriptEnabled = true
                    settings.safeBrowsingEnabled = true
                    loadUrl(url)
                }
            }, update = {
                it.loadUrl(url)
            })
        }
    }
)
© www.soinside.com 2019 - 2024. All rights reserved.