Skip to content

Commit 1a4d6d0

Browse files
update SpinningProgressIndicator
* calculates draw area dimensions to be equal to each other
1 parent 48e8028 commit 1a4d6d0

File tree

1 file changed

+65
-40
lines changed

1 file changed

+65
-40
lines changed

progressindicator/src/main/java/com/smarttoolfactory/progressindicator/SpinningProgressIndicator.kt

Lines changed: 65 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.smarttoolfactory.progressindicator
22

33
import androidx.compose.animation.core.*
44
import androidx.compose.foundation.Canvas
5+
import androidx.compose.foundation.border
56
import androidx.compose.foundation.layout.size
67
import androidx.compose.runtime.Composable
78
import androidx.compose.runtime.getValue
@@ -19,87 +20,111 @@ enum class SpinnerShape {
1920
Rect, RoundedRect
2021
}
2122

23+
/**
24+
* Indeterminate Material Design spinning progress indicator with rectangle or rounded rectangle
25+
* shape.
26+
* @param staticItemColor color of the spinning items
27+
* @param dynamicItemColor color of the stationary items
28+
* @param spinnerShape shape of the items whether [SpinnerShape.Rect] or [SpinnerShape.RoundedRect]
29+
* @param durationMillis duration of one cycle of spinning
30+
*/
2231
@Composable
2332
fun SpinningProgressIndicator(
2433
modifier: Modifier = Modifier,
2534
staticItemColor: Color = StaticItemColor,
2635
dynamicItemColor: Color = DynamicItemColor,
2736
spinnerShape: SpinnerShape = SpinnerShape.RoundedRect,
28-
durationInMillis: Int = 1000
37+
durationMillis: Int = 1000
2938
) {
3039

3140
val count = 12
41+
val coefficient = 360f / count
3242

3343
val infiniteTransition = rememberInfiniteTransition()
3444
val angle by infiniteTransition.animateFloat(
3545
initialValue = 0f,
3646
targetValue = count.toFloat(),
3747
animationSpec = infiniteRepeatable(
38-
animation = tween(durationInMillis, easing = LinearEasing),
48+
animation = tween(
49+
durationMillis = durationMillis,
50+
easing = LinearEasing
51+
),
3952
repeatMode = RepeatMode.Restart
4053
)
4154
)
4255

56+
Canvas(
57+
modifier = modifier
58+
.size(48.dp)
59+
.border(1.dp, Color.Red)
60+
) {
4361

44-
Canvas(modifier = modifier.size(48.dp)) {
62+
var canvasWidth = size.width
63+
var canvasHeight = size.height
4564

46-
val canvasWidth = size.width
47-
val canvasHeight = size.height
65+
if (canvasHeight < canvasWidth) {
66+
canvasWidth = canvasHeight
67+
} else {
68+
canvasHeight = canvasWidth
69+
}
70+
71+
val itemWidth = canvasWidth * .3f
72+
val itemHeight = canvasHeight / 12
73+
74+
val cornerRadius = itemWidth.coerceAtMost(itemHeight) / 2
75+
76+
val horizontalOffset = (size.width - size.height).coerceAtLeast(0f) / 2
77+
val verticalOffset = (size.height - size.width).coerceAtLeast(0f) / 2
4878

49-
val width = canvasWidth * .3f
50-
val height = canvasHeight / 12
79+
val topLeftOffset = Offset(
80+
x = horizontalOffset + canvasWidth - itemWidth,
81+
y = verticalOffset + (canvasHeight - itemHeight) / 2
82+
)
5183

52-
val cornerRadius = width.coerceAtMost(height) / 2
84+
val size = Size(itemWidth, itemHeight)
5385

5486
// Stationary items
5587
for (i in 0..360 step 360 / count) {
5688
rotate(i.toFloat()) {
5789
if (spinnerShape == SpinnerShape.RoundedRect) {
5890
drawRoundRect(
5991
color = staticItemColor,
60-
topLeft = Offset(canvasWidth - width, (canvasHeight - height) / 2),
61-
size = Size(width, height),
92+
topLeft = topLeftOffset,
93+
size = size,
6294
cornerRadius = CornerRadius(cornerRadius, cornerRadius)
6395
)
6496
} else {
6597
drawRect(
6698
color = staticItemColor,
67-
topLeft = Offset(canvasWidth - width, (canvasHeight - height) / 2),
68-
size = Size(width, height)
99+
topLeft = topLeftOffset,
100+
size = size,
69101
)
70102
}
71103
}
72104
}
73105

74-
val coefficient = 360f / count
75-
76-
// Dynamic items
77-
for (i in 0..count / 2) {
78-
rotate((angle.toInt() + i) * coefficient) {
79-
if (spinnerShape == SpinnerShape.RoundedRect) {
80-
drawRoundRect(
81-
color = dynamicItemColor.copy(
82-
alpha = (0.2f + 0.15f * i).coerceIn(
83-
0f, 1f
84-
)
85-
),
86-
topLeft = Offset(canvasWidth - width, (canvasHeight - height) / 2),
87-
size = Size(width, height),
88-
cornerRadius = CornerRadius(cornerRadius, cornerRadius)
89-
)
90-
} else {
91-
drawRect(
92-
color = dynamicItemColor.copy(
93-
alpha = (0.2f + 0.15f * i).coerceIn(
94-
0f, 1f
95-
)
96-
),
97-
topLeft = Offset(canvasWidth - width, (canvasHeight - height) / 2),
98-
size = Size(width, height)
99-
)
100-
}
106+
// Dynamic items
107+
for (i in 0..count / 2) {
108+
rotate((angle.toInt() + i) * coefficient) {
109+
if (spinnerShape == SpinnerShape.RoundedRect) {
110+
drawRoundRect(
111+
color = dynamicItemColor.copy(alpha = (0.2f + 0.15f * i).coerceIn(0f, 1f)),
112+
topLeft = topLeftOffset,
113+
size = size,
114+
cornerRadius = CornerRadius(cornerRadius, cornerRadius)
115+
)
116+
} else {
117+
drawRect(
118+
color = dynamicItemColor.copy(
119+
alpha = (0.2f + 0.15f * i).coerceIn(
120+
0f, 1f
121+
)
122+
),
123+
topLeft = topLeftOffset,
124+
size = size,
125+
)
101126
}
102127
}
128+
}
103129
}
104130
}
105-

0 commit comments

Comments
 (0)