Coverage Summary for Class: PlayStopIconState (com.vsevolodganin.clicktrack.ui.piece)
Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
PlayStopIconState |
0%
(0/1)
|
0%
(0/1)
|
|
0%
(0/2)
|
0%
(0/18)
|
package com.vsevolodganin.clicktrack.ui.piece
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.animateOffset
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.updateTransition
import androidx.compose.material.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.PathBuilder
import androidx.compose.ui.unit.dp
import com.vsevolodganin.clicktrack.ui.piece.PlayStopIconState.PLAY
import com.vsevolodganin.clicktrack.ui.piece.PlayStopIconState.STOP
import com.vsevolodganin.clicktrack.utils.compose.Preview
@Composable
fun PlayStopButton(isPlaying: Boolean, onToggle: () -> Unit, modifier: Modifier = Modifier, enableInsets: Boolean = true) {
FloatingActionButton(
onClick = onToggle,
modifier = modifier,
enableInsets = enableInsets,
) {
PlayStopIcon(isPlaying)
}
}
private enum class PlayStopIconState {
PLAY,
STOP,
}
@Composable
fun PlayStopIcon(isPlaying: Boolean) {
val transition = updateTransition(targetState = if (isPlaying) STOP else PLAY)
@Composable
fun Transition<PlayStopIconState>.animatePoint(targetValueByState: @Composable (state: PlayStopIconState) -> Offset): State<Offset> {
return animateOffset(
transitionSpec = {
spring(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessMedium,
)
},
targetValueByState = targetValueByState,
)
}
val pointA by transition.animatePoint { state ->
when (state) {
PLAY -> Offset(8f, 5f)
STOP -> Offset(6f, 6f)
}
}
val pointB by transition.animatePoint { state ->
when (state) {
PLAY -> Offset(19f, 12f)
STOP -> Offset(18f, 6f)
}
}
val pointC by transition.animatePoint { state ->
when (state) {
PLAY -> Offset(19f, 12f)
STOP -> Offset(18f, 18f)
}
}
val pointD by transition.animatePoint { state ->
when (state) {
PLAY -> Offset(8f, 19f)
STOP -> Offset(6f, 18f)
}
}
Icon(
imageVector = iconAsset(
pointA,
pointB,
pointC,
pointD,
),
contentDescription = null,
)
}
private fun iconAsset(a: Offset, b: Offset, c: Offset, d: Offset): ImageVector {
return ImageVector.Builder(defaultWidth = 24.dp, defaultHeight = 24.dp, viewportWidth = 24f, viewportHeight = 24f)
.addPath(
pathData = PathBuilder()
.moveTo(a)
.lineTo(b)
.lineTo(c)
.lineTo(d)
.close()
.nodes,
fill = SolidColor(Color.White),
)
.build()
}
private fun PathBuilder.moveTo(point: Offset) = moveTo(point.x, point.y)
private fun PathBuilder.lineTo(point: Offset) = lineTo(point.x, point.y)
@Preview
@Composable
private fun Preview() {
PlayStopButton(
isPlaying = false,
onToggle = {},
)
}