@@ -62,8 +62,12 @@ import kotlinx.coroutines.CoroutineScope
6262import kotlinx.coroutines.flow.collectLatest
6363import kotlinx.coroutines.launch
6464import top.yukonga.miuix.kmp.utils.LocalOverScrollState
65+ import top.yukonga.miuix.kmp.utils.LocalScrollCoordinatorState
6566import top.yukonga.miuix.kmp.utils.OverScrollState
67+ import top.yukonga.miuix.kmp.utils.ScrollPriority
6668import top.yukonga.miuix.kmp.utils.getWindowSize
69+ import top.yukonga.miuix.kmp.utils.overScrollVertical
70+ import top.yukonga.miuix.kmp.utils.rememberScrollCoordinator
6771import kotlin.math.PI
6872import kotlin.math.cos
6973import 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 (
0 commit comments