Skip to content

Commit 6456048

Browse files
committed
调整下拉动画
1 parent c40222b commit 6456048

File tree

1 file changed

+62
-57
lines changed

1 file changed

+62
-57
lines changed

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

Lines changed: 62 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
package top.yukonga.miuix.kmp.basic
22

3-
import androidx.compose.animation.AnimatedVisibility
43
import androidx.compose.animation.core.Animatable
54
import androidx.compose.animation.core.AnimationSpec
5+
import androidx.compose.animation.core.CubicBezierEasing
66
import androidx.compose.animation.core.LinearEasing
7-
import androidx.compose.animation.core.LinearOutSlowInEasing
87
import androidx.compose.animation.core.RepeatMode
98
import androidx.compose.animation.core.animateFloat
109
import androidx.compose.animation.core.infiniteRepeatable
1110
import androidx.compose.animation.core.rememberInfiniteTransition
1211
import androidx.compose.animation.core.snap
1312
import androidx.compose.animation.core.tween
1413
import androidx.compose.foundation.Canvas
14+
import androidx.compose.foundation.layout.Arrangement
1515
import androidx.compose.foundation.layout.Box
1616
import androidx.compose.foundation.layout.Column
1717
import androidx.compose.foundation.layout.fillMaxSize
@@ -178,21 +178,16 @@ fun RefreshHeader(
178178
}
179179
}
180180

181-
val textAlpha by derivedStateOf {
181+
val textAlpha by derivedStateOf{
182182
when (pullToRefreshState.refreshState) {
183-
RefreshState.Pulling -> {
184-
if (pullProgress > 0.5f) (pullProgress - 0.5f) * 2f else 0f
185-
}
186-
187-
RefreshState.RefreshComplete -> {
188-
(1f - refreshCompleteAnimProgress * 1.2f).coerceAtLeast(0f)
189-
}
190-
183+
RefreshState.Idle -> 0f
184+
RefreshState.Pulling -> if (pullProgress > 0.6f) (pullProgress - 0.5f) * 2f else 0f
185+
RefreshState.RefreshComplete -> (1f - refreshCompleteAnimProgress * 1.8f).coerceAtLeast(0f)
191186
else -> 1f
192187
}
193188
}
194189

195-
val headerHeight = with(density) {
190+
val sHeight = with(density) {
196191
when (pullToRefreshState.refreshState) {
197192
RefreshState.Idle -> 0.dp
198193
RefreshState.Pulling -> circleSize * pullProgress
@@ -202,31 +197,47 @@ fun RefreshHeader(
202197
}.coerceAtMost(maxDrag.toDp())
203198
}
204199

200+
201+
val headerHeight = with(density) {
202+
when (pullToRefreshState.refreshState) {
203+
RefreshState.Idle -> 0.dp
204+
RefreshState.Pulling -> (circleSize+36.dp) * pullProgress
205+
RefreshState.ThresholdReached -> (circleSize+36.dp) + (dragOffset - thresholdOffset).toDp()
206+
RefreshState.Refreshing -> (circleSize+36.dp)
207+
RefreshState.RefreshComplete -> (circleSize+36.dp).coerceIn(0.dp, (circleSize+36.dp) - (circleSize+36.dp) * refreshCompleteAnimProgress)
208+
}.coerceAtMost(maxDrag.toDp()+36.dp)
209+
}
210+
211+
212+
213+
// Header layout
205214
Column(
206-
modifier = modifier.fillMaxWidth(),
207-
horizontalAlignment = Alignment.CenterHorizontally
215+
modifier = modifier
216+
.fillMaxWidth()
217+
.height(headerHeight),
218+
horizontalAlignment = Alignment.CenterHorizontally,
219+
verticalArrangement = Arrangement.Top
208220
) {
209221
RefreshContent(
210-
modifier = Modifier.height(headerHeight),
222+
modifier = Modifier.height(sHeight),
211223
circleSize = circleSize
212224
) {
213225
val ringStrokeWidthPx = circleSize.toPx() / 11
214-
val indicatorRadiusPx = size.minDimension / 2
215-
val center = Offset(size.width / 2, size.height / 1.8f)
226+
val indicatorRadiusPx = (size.minDimension / 2).coerceAtLeast(circleSize.toPx() / 3.5f)
227+
val center = Offset(circleSize.toPx() / 2, circleSize.toPx() / 1.8f)
228+
val alpha = (pullProgress-0.2f).coerceAtLeast(0f)
216229

217230
when (pullToRefreshState.refreshState) {
218231
RefreshState.Idle -> return@RefreshContent
219232
RefreshState.Pulling -> {
220-
if (pullProgress > 0.3f) {
221-
drawInitialState(
222-
center = center,
223-
radius = indicatorRadiusPx,
224-
strokeWidth = ringStrokeWidthPx,
225-
color = color,
226-
alpha = pullProgress,
227-
refreshProgress = pullProgress
228-
)
229-
}
233+
drawInitialState(
234+
center = center,
235+
radius = indicatorRadiusPx,
236+
strokeWidth = ringStrokeWidthPx,
237+
color = color,
238+
alpha = alpha
239+
)
240+
230241
}
231242

232243
RefreshState.ThresholdReached -> drawThresholdExceededState(
@@ -257,20 +268,15 @@ fun RefreshHeader(
257268
}
258269
}
259270

260-
AnimatedVisibility(
261-
visible = pullProgress >= 0.5f
262-
&& pullToRefreshState.refreshState != RefreshState.Idle
263-
&& pullToRefreshState.refreshState != RefreshState.RefreshComplete
264-
) {
265-
Text(
266-
text = refreshText,
267-
style = refreshTextStyle,
268-
color = color,
269-
modifier = Modifier
270-
.alpha(textAlpha)
271-
.padding(top = 6.dp)
272-
)
273-
}
271+
// Animated text with height and alpha
272+
Text(
273+
text = refreshText,
274+
style = refreshTextStyle,
275+
color = color,
276+
modifier = Modifier
277+
.padding(top = 6.dp)
278+
.alpha(textAlpha)
279+
)
274280
}
275281
}
276282

@@ -323,13 +329,13 @@ private fun DrawScope.drawInitialState(
323329
radius: Float,
324330
strokeWidth: Float,
325331
color: Color,
326-
alpha: Float,
327-
refreshProgress: Float
332+
alpha: Float
328333
) {
334+
329335
val alphaColor = color.copy(alpha = alpha)
330336
drawCircle(
331337
color = alphaColor,
332-
radius = radius * refreshProgress,
338+
radius = radius,
333339
center = center,
334340
style = Stroke(strokeWidth, cap = StrokeCap.Round)
335341
)
@@ -431,17 +437,16 @@ private fun DrawScope.drawRefreshCompleteState(
431437
color: Color,
432438
refreshCompleteProgress: Float
433439
) {
434-
val animatedRadius = radius * (1f - refreshCompleteProgress)
435-
val alphaColor = color.copy(alpha = 1f - refreshCompleteProgress)
436-
437-
if (animatedRadius > 0) {
438-
drawCircle(
439-
color = alphaColor,
440-
radius = animatedRadius,
441-
center = center,
442-
style = Stroke(strokeWidth, cap = StrokeCap.Round)
443-
)
444-
}
440+
val animatedRadius = radius * ((1f - refreshCompleteProgress).coerceAtLeast(0.9f))
441+
val alphaColor = color.copy(alpha = (1f - refreshCompleteProgress-0.2f).coerceAtLeast(0f))
442+
443+
drawCircle(
444+
color = alphaColor,
445+
radius = animatedRadius,
446+
center = center,
447+
style = Stroke(strokeWidth, cap = StrokeCap.Round)
448+
)
449+
445450
}
446451

447452
/**
@@ -592,7 +597,7 @@ class PullToRefreshState(
592597
targetValue = 1f,
593598
animationSpec = tween(
594599
durationMillis = 200,
595-
easing = LinearOutSlowInEasing
600+
easing = CubicBezierEasing(0f, 0f, 0f, 0.37f)
596601
)
597602
) {
598603
_refreshCompleteAnimProgress.floatValue = this.value
@@ -676,7 +681,7 @@ class PullToRefreshState(
676681
targetValue = refreshThresholdOffset,
677682
animationSpec = tween(
678683
durationMillis = 200,
679-
easing = LinearOutSlowInEasing
684+
easing = CubicBezierEasing(0f, 0f, 0f, 0.37f)
680685
)
681686
)
682687
rawDragOffset = refreshThresholdOffset

0 commit comments

Comments
 (0)