PullRefresh: Invoke callback only when initiated by user (#10201)

This commit is contained in:
Ivan Iskandar 2023-12-02 23:19:43 +07:00 committed by GitHub
parent e5a22eafe7
commit e5518b7615
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -47,22 +47,11 @@ fun PullRefresh(
content: @Composable () -> Unit, content: @Composable () -> Unit,
) { ) {
val state = rememberPullToRefreshState( val state = rememberPullToRefreshState(
initialRefreshing = refreshing, isRefreshing = refreshing,
extraVerticalOffset = indicatorPadding.calculateTopPadding(), extraVerticalOffset = indicatorPadding.calculateTopPadding(),
enabled = enabled, enabled = enabled,
onRefresh = onRefresh,
) )
if (state.isRefreshing) {
LaunchedEffect(true) {
onRefresh()
}
}
LaunchedEffect(refreshing) {
if (refreshing && !state.isRefreshing) {
state.startRefreshAnimated()
} else if (!refreshing && state.isRefreshing) {
state.endRefreshAnimated()
}
}
Box(modifier.nestedScroll(state.nestedScrollConnection)) { Box(modifier.nestedScroll(state.nestedScrollConnection)) {
content() content()
@ -94,10 +83,11 @@ fun PullRefresh(
@Composable @Composable
private fun rememberPullToRefreshState( private fun rememberPullToRefreshState(
initialRefreshing: Boolean, isRefreshing: Boolean,
extraVerticalOffset: Dp, extraVerticalOffset: Dp,
positionalThreshold: Dp = 64.dp, positionalThreshold: Dp = 64.dp,
enabled: () -> Boolean = { true }, enabled: () -> Boolean = { true },
onRefresh: () -> Unit,
): PullToRefreshStateImpl { ): PullToRefreshStateImpl {
val density = LocalDensity.current val density = LocalDensity.current
val extraVerticalOffsetPx = with(density) { extraVerticalOffset.toPx() } val extraVerticalOffsetPx = with(density) { extraVerticalOffset.toPx() }
@ -106,18 +96,29 @@ private fun rememberPullToRefreshState(
extraVerticalOffset, extraVerticalOffset,
positionalThresholdPx, positionalThresholdPx,
enabled, enabled,
onRefresh,
saver = PullToRefreshStateImpl.Saver( saver = PullToRefreshStateImpl.Saver(
extraVerticalOffset = extraVerticalOffsetPx, extraVerticalOffset = extraVerticalOffsetPx,
positionalThreshold = positionalThresholdPx, positionalThreshold = positionalThresholdPx,
enabled = enabled, enabled = enabled,
onRefresh = onRefresh,
), ),
) { ) {
PullToRefreshStateImpl( PullToRefreshStateImpl(
initialRefreshing = initialRefreshing, initialRefreshing = isRefreshing,
extraVerticalOffset = extraVerticalOffsetPx, extraVerticalOffset = extraVerticalOffsetPx,
positionalThreshold = positionalThresholdPx, positionalThreshold = positionalThresholdPx,
enabled = enabled, enabled = enabled,
onRefresh = onRefresh,
) )
}.also {
LaunchedEffect(isRefreshing) {
if (isRefreshing && !it.isRefreshing) {
it.startRefreshAnimated()
} else if (!isRefreshing && it.isRefreshing) {
it.endRefreshAnimated()
}
}
} }
} }
@ -128,6 +129,7 @@ private fun rememberPullToRefreshState(
* @param extraVerticalOffset Extra vertical offset, in pixels, for the "refreshing" state * @param extraVerticalOffset Extra vertical offset, in pixels, for the "refreshing" state
* @param initialRefreshing The initial refreshing value of [PullToRefreshState] * @param initialRefreshing The initial refreshing value of [PullToRefreshState]
* @param enabled a callback used to determine whether scroll events are to be handled by this * @param enabled a callback used to determine whether scroll events are to be handled by this
* @param onRefresh a callback to run when pull-to-refresh action is triggered by user
* [PullToRefreshState] * [PullToRefreshState]
*/ */
private class PullToRefreshStateImpl( private class PullToRefreshStateImpl(
@ -135,6 +137,7 @@ private class PullToRefreshStateImpl(
private val extraVerticalOffset: Float, private val extraVerticalOffset: Float,
override val positionalThreshold: Float, override val positionalThreshold: Float,
enabled: () -> Boolean, enabled: () -> Boolean,
private val onRefresh: () -> Unit,
) : PullToRefreshState { ) : PullToRefreshState {
override val progress get() = adjustedDistancePulled / positionalThreshold override val progress get() = adjustedDistancePulled / positionalThreshold
@ -215,6 +218,7 @@ private class PullToRefreshStateImpl(
if (isRefreshing) return 0f // Already refreshing, do nothing if (isRefreshing) return 0f // Already refreshing, do nothing
// Trigger refresh // Trigger refresh
if (adjustedDistancePulled > positionalThreshold) { if (adjustedDistancePulled > positionalThreshold) {
onRefresh()
startRefreshAnimated() startRefreshAnimated()
} else { } else {
animateTo(0f) animateTo(0f)
@ -263,6 +267,7 @@ private class PullToRefreshStateImpl(
extraVerticalOffset: Float, extraVerticalOffset: Float,
positionalThreshold: Float, positionalThreshold: Float,
enabled: () -> Boolean, enabled: () -> Boolean,
onRefresh: () -> Unit,
) = Saver<PullToRefreshStateImpl, Boolean>( ) = Saver<PullToRefreshStateImpl, Boolean>(
save = { it.isRefreshing }, save = { it.isRefreshing },
restore = { isRefreshing -> restore = { isRefreshing ->
@ -271,6 +276,7 @@ private class PullToRefreshStateImpl(
extraVerticalOffset = extraVerticalOffset, extraVerticalOffset = extraVerticalOffset,
positionalThreshold = positionalThreshold, positionalThreshold = positionalThreshold,
enabled = enabled, enabled = enabled,
onRefresh = onRefresh,
) )
}, },
) )