Reputation: 131
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.
Upvotes: 9
Views: 7226
Reputation: 867
I'm using Scaffold where in the content I add a Column with verticalScroll(rememberScrollState()). I tested few sites and works in my case.
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)
})
}
}
)
Upvotes: 0
Reputation: 126
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 = { }
)
}
Upvotes: 5
Reputation: 359
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)
}
}
Upvotes: 5
Reputation: 408
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))
}
)
Upvotes: 0
Reputation: 6810
You need to use a NestedScrollConnection
object, and pass it to a nestedSCroll modifier on the outer view . Here's a basic example
Upvotes: 2