Skip to content

Commit bc547d9

Browse files
committed
library: Add InfiniteProgressIndicator Component
1 parent 4e53526 commit bc547d9

File tree

2 files changed

+76
-2
lines changed

2 files changed

+76
-2
lines changed

composeApp/src/commonMain/kotlin/component/OtherComponent.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import androidx.compose.runtime.getValue
1616
import androidx.compose.runtime.mutableStateOf
1717
import androidx.compose.runtime.remember
1818
import androidx.compose.runtime.setValue
19+
import androidx.compose.ui.Alignment
1920
import androidx.compose.ui.Modifier
2021
import androidx.compose.ui.platform.LocalFocusManager
2122
import androidx.compose.ui.text.font.FontWeight
@@ -27,6 +28,7 @@ import top.yukonga.miuix.kmp.basic.ButtonDefaults
2728
import top.yukonga.miuix.kmp.basic.Card
2829
import top.yukonga.miuix.kmp.basic.CircularProgressIndicator
2930
import top.yukonga.miuix.kmp.basic.Icon
31+
import top.yukonga.miuix.kmp.basic.InfiniteProgressIndicator
3032
import top.yukonga.miuix.kmp.basic.LinearProgressIndicator
3133
import top.yukonga.miuix.kmp.basic.Slider
3234
import top.yukonga.miuix.kmp.basic.SliderDefaults.SliderHapticEffect
@@ -186,7 +188,7 @@ fun OtherComponent(padding: PaddingValues) {
186188
)
187189
}
188190

189-
SmallTitle(text = "LinearProgressIndicator")
191+
SmallTitle(text = "ProgressIndicator")
190192
progressValues.forEach { progressValue ->
191193
LinearProgressIndicator(
192194
progress = progressValue,
@@ -208,6 +210,10 @@ fun OtherComponent(padding: PaddingValues) {
208210
progress = progressValue
209211
)
210212
}
213+
InfiniteProgressIndicator(
214+
modifier = Modifier
215+
.align(alignment = Alignment.CenterVertically)
216+
)
211217
}
212218

213219
SmallTitle(text = "TextField")

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

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ import androidx.compose.ui.unit.Dp
2424
import androidx.compose.ui.unit.dp
2525
import top.yukonga.miuix.kmp.basic.ProgressIndicatorDefaults.ProgressIndicatorColors
2626
import top.yukonga.miuix.kmp.theme.MiuixTheme
27+
import kotlin.math.PI
28+
import kotlin.math.cos
29+
import kotlin.math.sin
2730

2831
/**
2932
* A [LinearProgressIndicator] with Miuix style.
@@ -260,6 +263,62 @@ fun CircularProgressIndicator(
260263
}
261264
}
262265

266+
/**
267+
* A [InfiniteProgressIndicator] with Miuix style.
268+
* The indicator is a circular indicator with an orbiting dot.
269+
*
270+
* @param modifier The modifier to be applied to the indicator.
271+
* @param color The color of the indicator.
272+
* @param size The size (diameter) of the circular indicator.
273+
* @param strokeWidth The width of the circular stroke.
274+
* @param orbitingDotSize The size of the orbiting dot.
275+
*/
276+
@Composable
277+
fun InfiniteProgressIndicator(
278+
modifier: Modifier = Modifier,
279+
color: Color = Color.Gray,
280+
size: Dp = ProgressIndicatorDefaults.DefaultInfiniteProgressIndicatorSize,
281+
strokeWidth: Dp = ProgressIndicatorDefaults.DefaultInfiniteProgressIndicatorStrokeWidth,
282+
orbitingDotSize: Dp = ProgressIndicatorDefaults.DefaultInfiniteProgressIndicatorOrbitingDotSize
283+
) {
284+
val rotationAnim = remember { Animatable(0f) }
285+
286+
LaunchedEffect(Unit) {
287+
rotationAnim.animateTo(
288+
targetValue = 360f,
289+
animationSpec = infiniteRepeatable(
290+
animation = tween(800, easing = LinearEasing),
291+
repeatMode = RepeatMode.Restart
292+
)
293+
)
294+
}
295+
296+
Canvas(modifier = modifier.size(size)) {
297+
val center = Offset(this.size.width / 2, this.size.height / 2)
298+
val radius = (size.toPx() - strokeWidth.toPx()) / 2
299+
300+
drawCircle(
301+
color = color,
302+
radius = radius,
303+
center = center,
304+
style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round)
305+
)
306+
307+
val orbitRadius = radius - 2 * orbitingDotSize.toPx()
308+
val angle = rotationAnim.value * PI.toFloat() / 180f
309+
val dotCenter = center + Offset(
310+
x = orbitRadius * cos(angle),
311+
y = orbitRadius * sin(angle)
312+
)
313+
314+
drawCircle(
315+
color = color,
316+
radius = orbitingDotSize.toPx(),
317+
center = dotCenter
318+
)
319+
}
320+
}
321+
263322
object ProgressIndicatorDefaults {
264323
/** The default height of [LinearProgressIndicator]. */
265324
val DefaultLinearProgressIndicatorHeight = 6.dp
@@ -270,8 +329,17 @@ object ProgressIndicatorDefaults {
270329
/** The default size of [CircularProgressIndicator]. */
271330
val DefaultCircularProgressIndicatorSize = 36.dp
272331

332+
/** The default stroke width of [InfiniteProgressIndicator]. */
333+
val DefaultInfiniteProgressIndicatorStrokeWidth = 2.dp
334+
335+
/** The default radius width of the orbiting dot in [InfiniteProgressIndicator]. */
336+
val DefaultInfiniteProgressIndicatorOrbitingDotSize = 2.dp
337+
338+
/** The default size of [InfiniteProgressIndicator]. */
339+
val DefaultInfiniteProgressIndicatorSize = 20.dp
340+
273341
/**
274-
* The default [ProgressIndicatorColors] used in [LinearProgressIndicator].
342+
* The default [ProgressIndicatorColors] used by [LinearProgressIndicator] and [CircularProgressIndicator].
275343
*/
276344
@Composable
277345
fun progressIndicatorColors(

0 commit comments

Comments
 (0)