11package top.yukonga.miuix.kmp.basic
22
3- import androidx.compose.animation.AnimatedVisibility
43import androidx.compose.animation.core.Animatable
54import androidx.compose.animation.core.AnimationSpec
5+ import androidx.compose.animation.core.CubicBezierEasing
66import androidx.compose.animation.core.LinearEasing
7- import androidx.compose.animation.core.LinearOutSlowInEasing
87import androidx.compose.animation.core.RepeatMode
98import androidx.compose.animation.core.animateFloat
109import androidx.compose.animation.core.infiniteRepeatable
1110import androidx.compose.animation.core.rememberInfiniteTransition
1211import androidx.compose.animation.core.snap
1312import androidx.compose.animation.core.tween
1413import androidx.compose.foundation.Canvas
14+ import androidx.compose.foundation.layout.Arrangement
1515import androidx.compose.foundation.layout.Box
1616import androidx.compose.foundation.layout.Column
1717import 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