Skip to content

Commit 300726f

Browse files
committed
fix: animate both searching loader rings
1 parent b86be71 commit 300726f

2 files changed

Lines changed: 36 additions & 13 deletions

File tree

app/src/main/java/to/bitkit/ui/sheets/hardware/HwSearchingSheet.kt

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package to.bitkit.ui.sheets.hardware
22

3+
import androidx.compose.animation.core.InfiniteTransition
34
import androidx.compose.animation.core.LinearEasing
45
import androidx.compose.animation.core.animateFloat
56
import androidx.compose.animation.core.infiniteRepeatable
@@ -28,19 +29,26 @@ import to.bitkit.ui.components.BodyM
2829
import to.bitkit.ui.components.BottomSheetPreview
2930
import to.bitkit.ui.components.Display
3031
import to.bitkit.ui.components.SecondaryButton
32+
import to.bitkit.ui.components.SheetSize
3133
import to.bitkit.ui.components.VerticalSpacer
3234
import to.bitkit.ui.scaffold.SheetTopBar
35+
import to.bitkit.ui.shared.modifiers.sheetHeight
3336
import to.bitkit.ui.shared.util.gradientBackground
3437
import to.bitkit.ui.theme.AppThemeSurface
3538
import to.bitkit.ui.theme.Colors
3639
import to.bitkit.ui.utils.withAccent
3740

3841
private val ANIMATION_SIZE = 280.dp
39-
private const val ARROWS_SIZE_RATIO = 0.82f
4042

41-
// Mirrors the Figma "Loading Animation" HW variants: four 90° keyframes, each a 1s linear
42-
// Smart Animate step, so the arrows complete a counter-clockwise turn every 4 seconds.
43-
private const val ARROWS_ROTATION_DURATION_MS = 4000
43+
// Relative sizes from the Figma "Loading Animation" HW frame (311 outer ring): arrows 256, inner ring 207.
44+
private const val ARROWS_SIZE_RATIO = 256f / 311f
45+
private const val INNER_RING_SIZE_RATIO = 207f / 311f
46+
47+
// Figma "Loading Animation" HW variants Smart-Animate linearly through their keyframes:
48+
// the arrows rotate 90° per 1s step (a counter-clockwise turn every 4s) while the two dashed
49+
// rings counter-rotate ~180° per 1s step (a turn every ~2s).
50+
private const val ARROWS_SPIN_MS = 4000
51+
private const val RING_SPIN_MS = 2000
4452

4553
@Composable
4654
fun HwSearchingSheet(
@@ -100,12 +108,9 @@ private fun Content(
100108
@Composable
101109
private fun SearchingAnimation(modifier: Modifier = Modifier) {
102110
val transition = rememberInfiniteTransition(label = "hw_searching")
103-
val rotation by transition.animateFloat(
104-
initialValue = 0f,
105-
targetValue = -360f,
106-
animationSpec = infiniteRepeatable(tween(durationMillis = ARROWS_ROTATION_DURATION_MS, easing = LinearEasing)),
107-
label = "arrows_rotation",
108-
)
111+
val arrowsRotation by transition.animateRotation(ARROWS_SPIN_MS, clockwise = false, label = "arrows")
112+
val outerRingRotation by transition.animateRotation(RING_SPIN_MS, clockwise = false, label = "outer_ring")
113+
val innerRingRotation by transition.animateRotation(RING_SPIN_MS, clockwise = true, label = "inner_ring")
109114

110115
Box(
111116
contentAlignment = Alignment.Center,
@@ -114,24 +119,42 @@ private fun SearchingAnimation(modifier: Modifier = Modifier) {
114119
Image(
115120
painter = painterResource(R.drawable.hw_searching_ring),
116121
contentDescription = null,
117-
modifier = Modifier.fillMaxSize()
122+
modifier = Modifier
123+
.fillMaxSize()
124+
.rotate(outerRingRotation)
125+
)
126+
Image(
127+
painter = painterResource(R.drawable.hw_searching_ring_inner),
128+
contentDescription = null,
129+
modifier = Modifier
130+
.fillMaxSize(INNER_RING_SIZE_RATIO)
131+
.rotate(innerRingRotation)
118132
)
119133
Image(
120134
painter = painterResource(R.drawable.hw_searching_arrows),
121135
contentDescription = null,
122136
modifier = Modifier
123137
.fillMaxSize(ARROWS_SIZE_RATIO)
124-
.rotate(rotation)
138+
.rotate(arrowsRotation)
125139
)
126140
}
127141
}
128142

143+
@Composable
144+
private fun InfiniteTransition.animateRotation(durationMillis: Int, clockwise: Boolean, label: String) =
145+
animateFloat(
146+
initialValue = 0f,
147+
targetValue = if (clockwise) 360f else -360f,
148+
animationSpec = infiniteRepeatable(tween(durationMillis = durationMillis, easing = LinearEasing)),
149+
label = label,
150+
)
151+
129152
@Preview(showSystemUi = true)
130153
@Composable
131154
private fun Preview() {
132155
AppThemeSurface {
133156
BottomSheetPreview {
134-
Content()
157+
Content(modifier = Modifier.sheetHeight(SheetSize.LARGE))
135158
}
136159
}
137160
}
8.07 KB
Loading

0 commit comments

Comments
 (0)