feat(common-ui): connect scroll view inside web view to top bar (#15)

This commit is contained in:
Diego Beraldin 2023-09-14 22:46:37 +02:00 committed by GitHub
parent 2b3253e7f9
commit 8a6f2ac45f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 7 deletions

View File

@ -8,6 +8,10 @@ import android.webkit.WebViewClient
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.viewinterop.AndroidView
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@ -15,9 +19,10 @@ import kotlinx.coroutines.flow.onEach
@SuppressLint("SetJavaScriptEnabled")
@Composable
actual fun CustomWebView(
navigator: WebViewNavigator,
modifier: Modifier,
url: String,
modifier: Modifier,
navigator: WebViewNavigator,
scrollConnection: NestedScrollConnection?,
) {
var webView: WebView? = null
@ -29,6 +34,7 @@ actual fun CustomWebView(
}.launchIn(this)
}
val density = LocalDensity.current.density
AndroidView(
modifier = modifier,
factory = { context ->
@ -44,7 +50,17 @@ actual fun CustomWebView(
}
settings.javaScriptEnabled = true
setOnScrollChangeListener { _, scrollX, scrollY, oldScrollX, oldScrollY ->
scrollConnection?.onPreScroll(
available = Offset(
x = (oldScrollX - scrollX) / density,
y = (oldScrollY - scrollY) / density,
), source = NestedScrollSource.Drag
)
}
loadUrl(url)
webView = this
}
},

View File

@ -2,10 +2,12 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
@Composable
expect fun CustomWebView(
navigator: WebViewNavigator = rememberWebViewNavigator(),
modifier: Modifier = Modifier,
url: String,
modifier: Modifier = Modifier,
navigator: WebViewNavigator = rememberWebViewNavigator(),
scrollConnection: NestedScrollConnection? = null,
)

View File

@ -10,6 +10,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
@ -28,10 +29,12 @@ class WebViewScreen(
@Composable
override fun Content() {
val navigator = remember { getNavigationCoordinator().getRootNavigator() }
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
Scaffold(
topBar = {
TopAppBar(
title = {},
scrollBehavior = scrollBehavior,
navigationIcon = {
Image(
modifier = Modifier.onClick {
@ -68,6 +71,7 @@ class WebViewScreen(
CustomWebView(
modifier = Modifier.fillMaxSize(),
navigator = webNavigator,
scrollConnection = scrollBehavior.nestedScrollConnection,
url = url,
)
}

View File

@ -2,12 +2,23 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.interop.UIKitView
import androidx.compose.ui.platform.LocalDensity
import kotlinx.cinterop.readValue
import kotlinx.cinterop.useContents
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import platform.CoreGraphics.CGRectZero
import platform.UIKit.UIScrollView
import platform.UIKit.UIScrollViewDelegateProtocol
import platform.WebKit.WKNavigation
import platform.WebKit.WKNavigationDelegateProtocol
import platform.WebKit.WKWebView
@ -16,9 +27,10 @@ import platform.darwin.NSObject
@Composable
actual fun CustomWebView(
navigator: WebViewNavigator,
modifier: Modifier,
url: String,
modifier: Modifier,
navigator: WebViewNavigator,
scrollConnection: NestedScrollConnection?,
) {
var webView: WKWebView? = null
@ -30,6 +42,10 @@ actual fun CustomWebView(
}.launchIn(this)
}
val density = LocalDensity.current.density
var lastOffsetX by remember { mutableStateOf(0f) }
var lastOffsetY by remember { mutableStateOf(0f) }
UIKitView(
factory = {
val config = WKWebViewConfiguration().apply {
@ -42,7 +58,6 @@ actual fun CustomWebView(
userInteractionEnabled = true
allowsBackForwardNavigationGestures = true
val navigationDelegate = object : NSObject(), WKNavigationDelegateProtocol {
override fun webView(
webView: WKWebView,
didFinishNavigation: WKNavigation?,
@ -51,6 +66,21 @@ actual fun CustomWebView(
}
}
this.navigationDelegate = navigationDelegate
this.scrollView.delegate = object : NSObject(), UIScrollViewDelegateProtocol {
override fun scrollViewDidScroll(scrollView: UIScrollView) {
scrollView.contentOffset.useContents {
val offsetX = (lastOffsetX - x).toFloat() / density
val offsetY = (lastOffsetY - y).toFloat() / density
scrollConnection?.onPreScroll(
available = Offset(offsetX, offsetY),
source = NestedScrollSource.Drag,
)
lastOffsetX = x.toFloat()
lastOffsetY = y.toFloat()
}
}
}
}.also {
webView = it
}