7

WebView is not scrolling inside Compose. I need to put the WebView inside BottomSheet using the Compose. The problem that WebView is not scrolling even if we use e.g. NestedWebView, or NestedScrollWebView. If I put WebView inside NestedScrollView it still doesn't react on scroll.

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")
                    }
                })

        }) {
    }

One of the workaround is to use verticalScroll and set the webview height as 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
                          ---//---

but there are a lot of sites that doesnt work with wrap_content for e.g. because of inner scrolling like this site https://contest.rippl.club/. This site doesn't work with that workaround. If we set the webview height as screen height that it still doesnt work, because the verticalScroll works as ScrollView, so it will just scroll until this height.

I've also checked this doc https://developer.android.com/jetpack/compose/gestures#parent-compose-child-view, but nothing works for webview case.

Arnold
  • 111
  • 1
  • 4
  • Have you found a solution yet? It doesn't work for me, here's the basic syntax of what I am trying. LazyColumn { items(size) { AndroidView { Webview { // scrollable content } } } } Here the web view doesn't scroll. If I take it out of the lazy column and render just one, I can scroll the content of the web view. I guess this is your problem too. – Karthik Sep 07 '22 at 16:47
  • It looks like the provided workaround does not work with `ModalBottomSheetLayout`. – DamienL Dec 15 '22 at 08:50

4 Answers4

1

You need to use a NestedScrollConnection object, and pass it to a nestedSCroll modifier on the outer view . Here's a basic example

user496854
  • 6,461
  • 10
  • 47
  • 84
  • Doesn't work. This is basically the main problem. NestedScroll doesn't compatible and so doesn't work with WebView. From the example you mentioned if you place the WebView instead of LazyColumn this example will not work. When you scroll the Webview the compose nestedScroll does not react. Same for NestedWebView. – Arnold Aug 17 '22 at 21:09
  • It should definitely work -- can you please post your actual code (with a NestedScrollConnection) that didn't work for you? – user496854 Aug 17 '22 at 21:42
  • You can check with the code you mentioned as an example, just use webview instead of LazyColumn. Basically the nestedScroll is already used in BottomSheet and properly implemented there. The problem that it doesn't react when you try to scroll webview. This is actually the compose issue, I hope they fix this soon, but for now I hope there is some working workaround for this. – Arnold Aug 18 '22 at 17:19
1

Here is a small sample code, which at least makes a WebView scrollable:

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

This answer helped: https://stackoverflow.com/a/70195667/4256193

It works for me:

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

There is the ease way to work around this issue. Ive got exact same case as you. All you need to do is implement pointerInput somehow like this:

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))
        }
    )
Dwane13
  • 190
  • 1
  • 2
  • 8