Skip to content

Commit b6a00df

Browse files
committed
library: Add a ScrollCoordinator
* Not perfect
1 parent 6b7680a commit b6a00df

File tree

4 files changed

+315
-16
lines changed

4 files changed

+315
-16
lines changed

example/src/commonMain/kotlin/SecondPage.kt

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import androidx.compose.runtime.mutableStateOf
1313
import androidx.compose.runtime.remember
1414
import androidx.compose.runtime.setValue
1515
import androidx.compose.ui.Modifier
16-
import androidx.compose.ui.input.nestedscroll.nestedScroll
1716
import androidx.compose.ui.unit.dp
1817
import kotlinx.coroutines.delay
1918
import top.yukonga.miuix.kmp.basic.Card
@@ -22,7 +21,6 @@ import top.yukonga.miuix.kmp.basic.ScrollBehavior
2221
import top.yukonga.miuix.kmp.basic.rememberPullToRefreshState
2322
import top.yukonga.miuix.kmp.extra.SuperDropdown
2423
import top.yukonga.miuix.kmp.utils.getWindowSize
25-
import top.yukonga.miuix.kmp.utils.overScrollVertical
2624
import top.yukonga.miuix.kmp.utils.scrollEndHaptic
2725

2826
@Composable
@@ -35,27 +33,27 @@ fun SecondPage(
3533

3634
val dropdownOptions = listOf("Option 1", "Option 2", "Option 3", "Option 4")
3735
val dropdownSelectedOption = remember { mutableStateOf(0) }
38-
var ii by remember { mutableStateOf(8) }
36+
var ii by remember { mutableStateOf(6) }
3937

4038
LaunchedEffect(pullToRefreshState.isRefreshing) {
4139
if (pullToRefreshState.isRefreshing) {
42-
delay(300)
40+
delay(350)
4341
pullToRefreshState.completeRefreshing { ii += 6 }
4442
}
4543
}
4644

4745
PullToRefresh(
4846
pullToRefreshState = pullToRefreshState,
47+
topAppBarScrollBehavior = topAppBarScrollBehavior,
48+
useScrollCoordinator = true,
4949
contentPadding = PaddingValues(top = padding.calculateTopPadding() + 12.dp)
5050
) {
5151
LazyColumn(
5252
modifier = Modifier
53+
.height(getWindowSize().height.dp)
5354
.then(
5455
if (scrollEndHaptic) Modifier.scrollEndHaptic() else Modifier
55-
)
56-
.overScrollVertical()
57-
.nestedScroll(topAppBarScrollBehavior.nestedScrollConnection)
58-
.height(getWindowSize().height.dp),
56+
),
5957
contentPadding = PaddingValues(top = padding.calculateTopPadding() + 12.dp),
6058
overscrollEffect = null
6159
) {

miuix/src/commonMain/kotlin/top/yukonga/miuix/kmp/basic/PullToRefresh.kt

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,12 @@ import kotlinx.coroutines.CoroutineScope
6262
import kotlinx.coroutines.flow.collectLatest
6363
import kotlinx.coroutines.launch
6464
import top.yukonga.miuix.kmp.utils.LocalOverScrollState
65+
import top.yukonga.miuix.kmp.utils.LocalScrollCoordinatorState
6566
import top.yukonga.miuix.kmp.utils.OverScrollState
67+
import top.yukonga.miuix.kmp.utils.ScrollPriority
6668
import top.yukonga.miuix.kmp.utils.getWindowSize
69+
import top.yukonga.miuix.kmp.utils.overScrollVertical
70+
import top.yukonga.miuix.kmp.utils.rememberScrollCoordinator
6771
import kotlin.math.PI
6872
import kotlin.math.cos
6973
import kotlin.math.max
@@ -82,6 +86,8 @@ import kotlin.math.sin
8286
* @param circleSize The size of the refresh indicator circle.
8387
* @param refreshTexts The texts to show when refreshing.
8488
* @param refreshTextStyle The style of the refresh text.
89+
* @param topAppBarScrollBehavior The scroll behavior of the top app bar to coordinate with.
90+
* @param useScrollCoordinator Whether to use the scroll coordinator for better integration.
8591
* @param onRefresh The callback to be called when the refresh is triggered.
8692
* @param content the content to be shown when the [PullToRefresh] is expanded.
8793
*/
@@ -94,6 +100,8 @@ fun PullToRefresh(
94100
circleSize: Dp = PullToRefreshDefaults.circleSize,
95101
refreshTexts: List<String> = PullToRefreshDefaults.refreshTexts,
96102
refreshTextStyle: TextStyle = PullToRefreshDefaults.refreshTextStyle,
103+
topAppBarScrollBehavior: ScrollBehavior? = null,
104+
useScrollCoordinator: Boolean = false,
97105
onRefresh: () -> Unit = {},
98106
content: @Composable () -> Unit
99107
) {
@@ -102,9 +110,19 @@ fun PullToRefresh(
102110
LaunchedEffect(pullToRefreshState.rawDragOffset) {
103111
pullToRefreshState.syncDragOffsetWithRawOffset()
104112
}
113+
105114
val overScrollState = LocalOverScrollState.current
106-
val nestedScrollConnection = remember(pullToRefreshState, overScrollState) {
107-
pullToRefreshState.createNestedScrollConnection(overScrollState)
115+
116+
val scrollCoordinator = if (useScrollCoordinator && topAppBarScrollBehavior != null) {
117+
rememberScrollCoordinator(
118+
topAppBarScrollBehavior = topAppBarScrollBehavior,
119+
pullToRefreshState = pullToRefreshState,
120+
overScrollState = overScrollState
121+
)
122+
} else null
123+
124+
val nestedScrollConnection = remember(pullToRefreshState, overScrollState, scrollCoordinator) {
125+
scrollCoordinator ?: pullToRefreshState.createNestedScrollConnection(overScrollState)
108126
}
109127
val pointerModifier = Modifier.pointerInput(Unit) {
110128
awaitPointerEventScope {
@@ -122,11 +140,20 @@ fun PullToRefresh(
122140
pullToRefreshState.handlePointerReleased(currentOnRefresh)
123141
}
124142

125-
val boxModifier = modifier
126-
.nestedScroll(nestedScrollConnection)
127-
.then(pointerModifier)
128-
129-
CompositionLocalProvider(LocalPullToRefreshState provides pullToRefreshState) {
143+
CompositionLocalProvider(
144+
LocalPullToRefreshState provides pullToRefreshState,
145+
LocalScrollCoordinatorState provides scrollCoordinator?.state
146+
) {
147+
val boxModifier = modifier
148+
.nestedScroll(nestedScrollConnection)
149+
.then(pointerModifier)
150+
.then(
151+
if (scrollCoordinator != null && scrollCoordinator.state.currentPriority == ScrollPriority.OverScroll) {
152+
Modifier.overScrollVertical()
153+
} else {
154+
Modifier
155+
}
156+
)
130157
Box(modifier = boxModifier) {
131158
Column {
132159
RefreshHeader(

miuix/src/commonMain/kotlin/top/yukonga/miuix/kmp/utils/Overscroll.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,4 +304,3 @@ class OverScrollState {
304304
* @see OverScrollState
305305
*/
306306
val LocalOverScrollState = compositionLocalOf { OverScrollState() }
307-

0 commit comments

Comments
 (0)