feat(common-ui): connect scroll view inside web view to top bar (#15)
This commit is contained in:
parent
2b3253e7f9
commit
8a6f2ac45f
@ -8,6 +8,10 @@ import android.webkit.WebViewClient
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.Modifier
|
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 androidx.compose.ui.viewinterop.AndroidView
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
@ -15,9 +19,10 @@ import kotlinx.coroutines.flow.onEach
|
|||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
@Composable
|
@Composable
|
||||||
actual fun CustomWebView(
|
actual fun CustomWebView(
|
||||||
navigator: WebViewNavigator,
|
|
||||||
modifier: Modifier,
|
|
||||||
url: String,
|
url: String,
|
||||||
|
modifier: Modifier,
|
||||||
|
navigator: WebViewNavigator,
|
||||||
|
scrollConnection: NestedScrollConnection?,
|
||||||
) {
|
) {
|
||||||
var webView: WebView? = null
|
var webView: WebView? = null
|
||||||
|
|
||||||
@ -29,6 +34,7 @@ actual fun CustomWebView(
|
|||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val density = LocalDensity.current.density
|
||||||
AndroidView(
|
AndroidView(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
factory = { context ->
|
factory = { context ->
|
||||||
@ -44,7 +50,17 @@ actual fun CustomWebView(
|
|||||||
}
|
}
|
||||||
settings.javaScriptEnabled = true
|
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)
|
loadUrl(url)
|
||||||
|
|
||||||
webView = this
|
webView = this
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2,10 +2,12 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
|
|||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
expect fun CustomWebView(
|
expect fun CustomWebView(
|
||||||
navigator: WebViewNavigator = rememberWebViewNavigator(),
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
url: String,
|
url: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
navigator: WebViewNavigator = rememberWebViewNavigator(),
|
||||||
|
scrollConnection: NestedScrollConnection? = null,
|
||||||
)
|
)
|
||||||
|
@ -10,6 +10,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
@ -28,10 +29,12 @@ class WebViewScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigator = remember { getNavigationCoordinator().getRootNavigator() }
|
val navigator = remember { getNavigationCoordinator().getRootNavigator() }
|
||||||
|
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {},
|
title = {},
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick {
|
modifier = Modifier.onClick {
|
||||||
@ -68,6 +71,7 @@ class WebViewScreen(
|
|||||||
CustomWebView(
|
CustomWebView(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
navigator = webNavigator,
|
navigator = webNavigator,
|
||||||
|
scrollConnection = scrollBehavior.nestedScrollConnection,
|
||||||
url = url,
|
url = url,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,23 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
|
|||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
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.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.interop.UIKitView
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import kotlinx.cinterop.readValue
|
import kotlinx.cinterop.readValue
|
||||||
|
import kotlinx.cinterop.useContents
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import platform.CoreGraphics.CGRectZero
|
import platform.CoreGraphics.CGRectZero
|
||||||
|
import platform.UIKit.UIScrollView
|
||||||
|
import platform.UIKit.UIScrollViewDelegateProtocol
|
||||||
import platform.WebKit.WKNavigation
|
import platform.WebKit.WKNavigation
|
||||||
import platform.WebKit.WKNavigationDelegateProtocol
|
import platform.WebKit.WKNavigationDelegateProtocol
|
||||||
import platform.WebKit.WKWebView
|
import platform.WebKit.WKWebView
|
||||||
@ -16,9 +27,10 @@ import platform.darwin.NSObject
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
actual fun CustomWebView(
|
actual fun CustomWebView(
|
||||||
navigator: WebViewNavigator,
|
|
||||||
modifier: Modifier,
|
|
||||||
url: String,
|
url: String,
|
||||||
|
modifier: Modifier,
|
||||||
|
navigator: WebViewNavigator,
|
||||||
|
scrollConnection: NestedScrollConnection?,
|
||||||
) {
|
) {
|
||||||
var webView: WKWebView? = null
|
var webView: WKWebView? = null
|
||||||
|
|
||||||
@ -30,6 +42,10 @@ actual fun CustomWebView(
|
|||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val density = LocalDensity.current.density
|
||||||
|
var lastOffsetX by remember { mutableStateOf(0f) }
|
||||||
|
var lastOffsetY by remember { mutableStateOf(0f) }
|
||||||
|
|
||||||
UIKitView(
|
UIKitView(
|
||||||
factory = {
|
factory = {
|
||||||
val config = WKWebViewConfiguration().apply {
|
val config = WKWebViewConfiguration().apply {
|
||||||
@ -42,7 +58,6 @@ actual fun CustomWebView(
|
|||||||
userInteractionEnabled = true
|
userInteractionEnabled = true
|
||||||
allowsBackForwardNavigationGestures = true
|
allowsBackForwardNavigationGestures = true
|
||||||
val navigationDelegate = object : NSObject(), WKNavigationDelegateProtocol {
|
val navigationDelegate = object : NSObject(), WKNavigationDelegateProtocol {
|
||||||
|
|
||||||
override fun webView(
|
override fun webView(
|
||||||
webView: WKWebView,
|
webView: WKWebView,
|
||||||
didFinishNavigation: WKNavigation?,
|
didFinishNavigation: WKNavigation?,
|
||||||
@ -51,6 +66,21 @@ actual fun CustomWebView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.navigationDelegate = navigationDelegate
|
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 {
|
}.also {
|
||||||
webView = it
|
webView = it
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user