compose loading 第一篇
需要了解下面几点
animateFloatAsState插值tween、spring、keyframes动画配合infiniteRepeatable重复动画Dialog、Canvas布局组件
案例说明
利用弧度加色值集合
Box(modifier = Modifier.fillMaxSize()) {
Dialog(
onDismissRequest = { /*TODO*/ },
properties = DialogProperties(dismissOnClickOutside = false, dismissOnBackPress = true)
) {
Box(
Modifier
.wrapContentSize()
.defaultMinSize(minWidth = 120.dp, minHeight = 120.dp)
.align(
Alignment.Center
)
.background(Color(0x80000000), RoundedCornerShape(12.dp))
) {
val durationMillis = 1000
var colors = listOf(Color.Yellow, Color.Red, Color.Green, Color.White)
var colorIndex by remember {
mutableIntStateOf(0)
}
var isRoll by remember {
mutableStateOf(false)
}
var ratioRoll = animateFloatAsState(
targetValue = if (isRoll) 360f else 0f, animationSpec = infiniteRepeatable(
animation = tween(
durationMillis, easing = LinearEasing
), repeatMode = RepeatMode.Restart
)
)
var isSweeping by remember {
mutableStateOf(false)
}
var ratio = animateFloatAsState(targetValue = if (!isSweeping) 330f else 30f, tween(
durationMillis, easing = FastOutLinearInEasing
), finishedListener = {
if (it == 30f) {
if (colorIndex < colors.size - 1) {
colorIndex++
} else {
colorIndex = 0
}
}
})
if (ratio.value == 30f) {
isSweeping = false
} else if (ratio.value == 330f) {
isSweeping = true
}
Canvas(modifier = Modifier
.size(40.dp)
.align(Alignment.Center), onDraw = {
val strokeWidth = 14.dp.value
drawArc(
color = colors[colorIndex],
startAngle = ratioRoll.value,
sweepAngle = ratio.value,
useCenter = false,
topLeft = Offset(strokeWidth.div(2), strokeWidth.div(2)),
style = Stroke(width = 10.dp.value, cap = StrokeCap.Round)
)
})
if (!isRoll) {
LaunchedEffect(key1 = "run", block = {
isRoll = true
})
}
}
}
}
线条加旋转绘制菊花
Box(modifier = Modifier.fillMaxSize()) {
Dialog(
onDismissRequest = { /*TODO*/ },
properties = DialogProperties(dismissOnClickOutside = false, dismissOnBackPress = true)
) {
Box(
Modifier
.wrapContentSize()
.defaultMinSize(minWidth = 120.dp, minHeight = 120.dp)
.align(
Alignment.Center
)
.background(Color(0x80000000), RoundedCornerShape(12.dp))
) {
val strokeWidth = 14.dp.value
val duration = 2000
var start by remember {
mutableStateOf(false)
}
var degree = animateIntAsState(
targetValue = if (start) 360 else 0, animationSpec = infiniteRepeatable(
animation = tween(
duration, easing = LinearEasing
)
)
)
Canvas(modifier = Modifier
.size(40.dp)
.align(Alignment.Center)
.rotate(degree.value.toFloat()), onDraw = {
var r = size.width.div(2)
val padding = r / 2
var rawX = r.times(cos(Math.toDegrees(45.0))) - strokeWidth.div(2)
var rawY = rawX
var stepPadding = padding.times(sin(Math.toDegrees(45.0)))
for (i in 0 until 8) {
rotate(i * 45f, pivot = Offset(r, r)) {
drawLine(
color = Color.White,
start = Offset((r - rawX).toFloat(), (r - rawY).toFloat()),
end = Offset(
r + stepPadding.toFloat(), r + stepPadding.toFloat()
),
strokeWidth = strokeWidth,
cap = StrokeCap.Round
)
}
}
})
if (!start) {
LaunchedEffect(key1 = "roll", block = {
start = true
})
}
}
}
}
圆环串珠转动效果
Box(modifier = Modifier.fillMaxSize()) {
Dialog(
onDismissRequest = { /*TODO*/ },
properties = DialogProperties(dismissOnClickOutside = false, dismissOnBackPress = true)
) {
Box(
Modifier
.wrapContentSize()
.defaultMinSize(minWidth = 120.dp, minHeight = 120.dp)
.align(
Alignment.Center
)
.background(Color(0x80000000), RoundedCornerShape(12.dp))
) {
val strokeWidth = 14.dp.value
val duration = 2000
var start by remember {
mutableStateOf(false)
}
var degree = animateIntAsState(
targetValue = if (start) 360 else 0, animationSpec = infiniteRepeatable(
animation = tween(
duration, easing = LinearEasing
)
)
)
Canvas(modifier = Modifier
.size(40.dp)
.align(Alignment.Center)
.rotate(degree.value.toFloat()), onDraw = {
var r = size.width.div(2)
val padding = r / 2
var rawX = r.times(cos(Math.toDegrees(45.0))) - strokeWidth.div(2)
var rawY = rawX
for (i in 0 until 8) {
rotate(i * 45f, pivot = Offset(r, r)) {
drawCircle(
color = Color.White,
radius = strokeWidth,
center = Offset((r - rawX).toFloat(), (r - rawY).toFloat())
)
}
}
})
if (!start) {
LaunchedEffect(key1 = "roll", block = {
start = true
})
}
}
}
}
螺旋串珠转动效果,旋转过程半径递增
Box(modifier = Modifier.fillMaxSize()) {
Dialog(
onDismissRequest = { /*TODO*/ },
properties = DialogProperties(dismissOnClickOutside = false, dismissOnBackPress = true)
) {
Box(
Modifier
.wrapContentSize()
.defaultMinSize(minWidth = 120.dp, minHeight = 120.dp)
.align(
Alignment.Center
)
.background(Color(0x80000000), RoundedCornerShape(12.dp))
) {
val strokeWidth = 4.dp.value
val duration = 2000
var start by remember {
mutableStateOf(false)
}
var degree = animateIntAsState(
targetValue = if (start) 360 else 0, animationSpec = infiniteRepeatable(
animation = tween(
duration, easing = LinearEasing
)
)
)
var dotRun by remember {
mutableStateOf(false)
}
var dotNum = animateIntAsState(targetValue = if (dotRun) 24 else 1,
animationSpec = tween(duration, easing = FastOutLinearInEasing),
finishedListener = {
if (it == 1) {
dotRun = true
} else if (it == 24) {
dotRun = false
}
})
Canvas(modifier = Modifier
.size(40.dp)
.align(Alignment.Center)
.rotate(degree.value.toFloat()), onDraw = {
var r = size.width.div(2)
for (i in 0 until dotNum.value) {
var padding = r * i / 24
var stepPadding = padding.times(sin(Math.toDegrees(45.0)))
rotate(i * 45f, pivot = Offset(r, r)) {
drawCircle(
color = Color.White,
radius = strokeWidth + (10 * i / 24f).toFloat(),
center = Offset(
r + stepPadding.toFloat(), r + stepPadding.toFloat()
),
alpha = i / 24f
)
}
}
})
if (!start) {
LaunchedEffect(key1 = "roll", block = {
start = true
dotRun = true
})
}
}
}
}