Skip to content

Commit 48e8028

Browse files
move circle indicators to separate file
1 parent 1f85e68 commit 48e8028

File tree

1 file changed

+49
-161
lines changed

1 file changed

+49
-161
lines changed
Lines changed: 49 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
package com.smarttoolfactory.progressindicator
22

3-
import androidx.compose.animation.*
43
import androidx.compose.animation.core.*
54
import androidx.compose.foundation.Canvas
6-
import androidx.compose.foundation.border
75
import androidx.compose.foundation.layout.size
86
import androidx.compose.runtime.Composable
97
import androidx.compose.runtime.getValue
10-
import androidx.compose.runtime.remember
118
import androidx.compose.ui.Modifier
129
import androidx.compose.ui.geometry.CornerRadius
1310
import androidx.compose.ui.geometry.Offset
1411
import androidx.compose.ui.geometry.Size
1512
import androidx.compose.ui.graphics.Color
1613
import androidx.compose.ui.graphics.drawscope.rotate
1714
import androidx.compose.ui.unit.dp
15+
import com.smarttoolfactory.progressindicator.ui.theme.DynamicItemColor
16+
import com.smarttoolfactory.progressindicator.ui.theme.StaticItemColor
17+
18+
enum class SpinnerShape {
19+
Rect, RoundedRect
20+
}
1821

19-
@OptIn(ExperimentalAnimationApi::class)
2022
@Composable
2123
fun SpinningProgressIndicator(
2224
modifier: Modifier = Modifier,
23-
show: Boolean = true
25+
staticItemColor: Color = StaticItemColor,
26+
dynamicItemColor: Color = DynamicItemColor,
27+
spinnerShape: SpinnerShape = SpinnerShape.RoundedRect,
28+
durationInMillis: Int = 1000
2429
) {
2530

2631
val count = 12
@@ -30,188 +35,71 @@ fun SpinningProgressIndicator(
3035
initialValue = 0f,
3136
targetValue = count.toFloat(),
3237
animationSpec = infiniteRepeatable(
33-
animation = tween(count * 60, easing = LinearEasing),
38+
animation = tween(durationInMillis, easing = LinearEasing),
3439
repeatMode = RepeatMode.Restart
3540
)
3641
)
3742

38-
val backgroundColor = Color.Gray
39-
// val foregroundColor = Color(0xff9E9E9E)
40-
val foregroundColor = Color(0xffCDCDCD)
4143

42-
AnimatedVisibility(
43-
visible = show,
44-
enter = scaleIn() + fadeIn(),
45-
exit = scaleOut() + fadeOut()
46-
) {
47-
Canvas(modifier = modifier.size(48.dp)) {
44+
Canvas(modifier = modifier.size(48.dp)) {
4845

49-
val canvasWidth = size.width
50-
val canvasHeight = size.height
46+
val canvasWidth = size.width
47+
val canvasHeight = size.height
5148

52-
val width = canvasWidth * .3f
53-
val height = canvasHeight / 10
49+
val width = canvasWidth * .3f
50+
val height = canvasHeight / 12
5451

55-
val cornerRadius = width.coerceAtMost(height) / 2
52+
val cornerRadius = width.coerceAtMost(height) / 2
5653

57-
// Stationary items
58-
for (i in 0..360 step 360 / count) {
59-
rotate(i.toFloat()) {
54+
// Stationary items
55+
for (i in 0..360 step 360 / count) {
56+
rotate(i.toFloat()) {
57+
if (spinnerShape == SpinnerShape.RoundedRect) {
6058
drawRoundRect(
61-
color = backgroundColor,
59+
color = staticItemColor,
6260
topLeft = Offset(canvasWidth - width, (canvasHeight - height) / 2),
6361
size = Size(width, height),
6462
cornerRadius = CornerRadius(cornerRadius, cornerRadius)
6563
)
66-
}
67-
}
68-
69-
val coefficient = 360f / count
70-
71-
// Dynamic items
72-
for (i in 0..count / 2) {
73-
rotate((angle.toInt() + i) * coefficient) {
74-
drawRoundRect(
75-
color = foregroundColor.copy(alpha = (0.2f + 0.15f * i).coerceIn(0f, 1f)),
64+
} else {
65+
drawRect(
66+
color = staticItemColor,
7667
topLeft = Offset(canvasWidth - width, (canvasHeight - height) / 2),
77-
size = Size(width, height),
78-
cornerRadius = CornerRadius(cornerRadius, cornerRadius)
68+
size = Size(width, height)
7969
)
8070
}
8171
}
8272
}
83-
}
84-
}
85-
86-
@OptIn(ExperimentalAnimationApi::class)
87-
@Composable
88-
fun SpinningCircleProgressIndicator(
89-
modifier: Modifier = Modifier,
90-
show: Boolean = true
91-
) {
92-
93-
val count = 8
94-
95-
val infiniteTransition = rememberInfiniteTransition()
96-
val angle by infiniteTransition.animateFloat(
97-
initialValue = 0f,
98-
targetValue = count.toFloat(),
99-
animationSpec = infiniteRepeatable(
100-
animation = tween(count * 120, easing = LinearEasing),
101-
repeatMode = RepeatMode.Restart
102-
)
103-
)
104-
105-
val backgroundColor = Color.DarkGray
106-
val foregroundColor = Color(0xff9E9E9E)
107-
108-
AnimatedVisibility(
109-
visible = show,
110-
enter = scaleIn() + fadeIn(),
111-
exit = scaleOut() + fadeOut()
112-
) {
113-
Canvas(modifier = modifier.size(48.dp)) {
114-
115-
val canvasWidth = size.width
116-
val canvasHeight = size.height
117-
118-
val radius = canvasWidth * .1f
119-
120-
// Stationary items
121-
for (i in 0..360 step 360 / count) {
122-
rotate(i.toFloat()) {
123-
drawCircle(
124-
color = backgroundColor,
125-
radius = radius,
126-
center = Offset(canvasWidth - radius, canvasHeight / 2),
127-
)
128-
}
129-
}
13073

13174
val coefficient = 360f / count
13275

13376
// Dynamic items
134-
for (i in 0..count) {
77+
for (i in 0..count / 2) {
13578
rotate((angle.toInt() + i) * coefficient) {
136-
drawCircle(
137-
color = foregroundColor.copy(
138-
alpha = (i.toFloat() / count).coerceIn(
139-
0f,
140-
1f
141-
)
142-
),
143-
radius = radius,
144-
center = Offset(canvasWidth - radius, canvasHeight / 2),
145-
)
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+
}
146101
}
147102
}
148-
}
149103
}
150104
}
151105

152-
@Composable
153-
fun ScaledCircleProgressIndicator(
154-
modifier: Modifier = Modifier
155-
) {
156-
val count = 8f
157-
158-
val infiniteTransition = rememberInfiniteTransition()
159-
val angle by infiniteTransition.animateFloat(
160-
initialValue = 0f,
161-
targetValue = count,
162-
infiniteRepeatable(
163-
animation = keyframes {
164-
durationMillis = 1100
165-
count * 0.8f at 700
166-
count * 0.1f at 150 with FastOutLinearInEasing
167-
count * 0.10f at 150
168-
}
169-
)
170-
)
171-
172-
val foregroundColor = Color.Red
173-
174-
val radiusList = remember { arrayListOf<Float>() }
175-
176-
Canvas(
177-
modifier = modifier
178-
.size(100.dp)
179-
.border(1.dp, Color.Red)
180-
) {
181-
182-
val canvasWidth = size.width
183-
val canvasHeight = size.height
184-
185-
186-
val coefficient = 360f / count
187-
188-
val radiusMax = canvasWidth / 2 * .1f
189-
190-
if (radiusList.isEmpty()) {
191-
repeat(6) {
192-
if (it == 0) {
193-
radiusList.add(radiusMax)
194-
} else {
195-
radiusList.add(radiusList[it - 1] * 1.2f)
196-
}
197-
}
198-
}
199-
200-
val radiusDynamicContainer = (canvasWidth - radiusList.last())
201-
202-
203-
// Dynamic items
204-
for (i in 0 until radiusList.size) {
205-
206-
val radius = radiusList[i]
207-
208-
rotate((angle + i) * coefficient) {
209-
drawCircle(
210-
color = foregroundColor.copy(alpha = ( i * .2f).coerceIn(0f, 1f)),
211-
radius = radius,
212-
center = Offset(radiusDynamicContainer, canvasHeight / 2),
213-
)
214-
}
215-
}
216-
}
217-
}

0 commit comments

Comments
 (0)