您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Jetpack Compose怎么實(shí)現(xiàn)動(dòng)畫(huà)效果,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
compose 為支持動(dòng)畫(huà)提供了大量的 api,通過(guò)這些 api 我們可以輕松實(shí)現(xiàn)動(dòng)畫(huà)效果
ps:這些 api 的原理與 Flutter 很接近,與原生的 api 相去甚遠(yuǎn)
你可以提前看看用 compose 實(shí)現(xiàn)的一個(gè)放大縮小動(dòng)畫(huà),總的來(lái)說(shuō)還是比較流暢:
所能處理屬性的種類:Float、Color、Dp、Size、Bounds、Offset、Rect、Int、IntOffset 和 IntSize
通過(guò) animate*AsState 我們可以實(shí)現(xiàn)單一屬性的動(dòng)畫(huà)效果,我們只需要提供目標(biāo)值就可以自動(dòng)從當(dāng)前進(jìn)度動(dòng)畫(huà)過(guò)渡到目標(biāo)值
實(shí)現(xiàn)放大動(dòng)畫(huà)
1.代碼
@Composable fun animSize() { val enable = remember { mutableStateOf(true) } val size = animateSizeAsState(targetValue = if (enable.value) Size(50f, 50f) else Size(300f, 300f)) Column( modifier = Modifier.fillMaxSize(1f), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Image( modifier = Modifier .size(size.value.width.dp, size.value.height.dp) .clickable { enable.value = !enable.value }, painter = painterResource(id = R.drawable.apple), contentDescription = "" ) } }
2.實(shí)現(xiàn)效果
實(shí)現(xiàn)顏色變化動(dòng)畫(huà)
1.代碼
@Composable fun animColor() { val enable = remember { mutableStateOf(true) } val colors = animateColorAsState(targetValue = if (enable.value) Color.Green else Color.Red) val size = animateIntSizeAsState( targetValue = if (enable.value) IntSize(100, 100) else IntSize( 300, 300 ) ) Column( modifier = Modifier.fillMaxWidth(1f), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Box( modifier = Modifier .size(size.value.width.dp, size.value.height.dp) .height(400.dp) .background( color = colors.value, shape = if (enable.value) RectangleShape else CircleShape ) ) { } } }
2.效果
Animatable 是一個(gè)值容器,我們可以通過(guò)調(diào)用 animateTo 實(shí)現(xiàn)動(dòng)畫(huà)效果。動(dòng)畫(huà)執(zhí)行過(guò)程中如果再次開(kāi)啟動(dòng)畫(huà)會(huì)中斷當(dāng)前動(dòng)畫(huà)。
Animatable 動(dòng)畫(huà)執(zhí)行過(guò)程中值的變化是在協(xié)程中執(zhí)行的,所以 animateTo 是一個(gè)掛起操作
1.代碼
@Composable fun animChangeColor() { val color = remember { Animatable(Color.Red) } val state = remember { mutableStateOf(true) } LaunchedEffect(state.value) { color.animateTo(if (state.value) Color.Red else Color.Magenta) } Box(Modifier.fillMaxSize(1f), contentAlignment = Alignment.Center) { Box( modifier = Modifier .background(color.value, shape = RoundedCornerShape(30.dp)) .size(200.dp) .clickable { state.value = !state.value }, contentAlignment = Alignment.Center ) { Text( text = "顏色動(dòng)畫(huà)", style = TextStyle(color = Color.White, fontSize = 40.sp) ) } } }
2.效果
使用 updateTransition 可以實(shí)現(xiàn)多個(gè)動(dòng)畫(huà)組合的效果。
例如:我們可以在動(dòng)畫(huà)執(zhí)行過(guò)程中同時(shí)執(zhí)行大小和顏色變化效果
本例中我們定義了一個(gè)枚舉用來(lái)控制動(dòng)畫(huà),枚舉可以定義多個(gè),分別用來(lái)對(duì)應(yīng)動(dòng)畫(huà)的多個(gè)狀態(tài)
1.代碼
@Composable fun animupdateTransition() { var state by remember { mutableStateOf(BoxState.Collapsed) } val transition = updateTransition(targetState = state, label = "") val round = transition.animateDp(label = "") { when (it) { BoxState.Collapsed -> 40.dp BoxState.Expanded -> 100.dp } } val color = transition.animateColor(label = "") { when (it) { BoxState.Collapsed -> Color.Red BoxState.Expanded -> Color.Green } } Box(Modifier.fillMaxSize(1f),contentAlignment = Alignment.Center) { Box( modifier = Modifier .size(300.dp) .background( color.value, shape = RoundedCornerShape(corner = CornerSize(round.value)) ) .clickable { state = if (state == BoxState.Collapsed) BoxState.Expanded else BoxState.Collapsed },contentAlignment = Alignment.Center ) { Text(text = "點(diǎn)擊開(kāi)始動(dòng)畫(huà)",style = TextStyle(color = Color.White,fontSize = 20.sp)) } } } private enum class BoxState { Collapsed, Expanded }
2.效果
rememberInfiniteTransition 的使用和 updateTransition 基本一樣,不同的是 rememberInfiniteTransition 的動(dòng)畫(huà)一旦開(kāi)始便會(huì)一直反復(fù)運(yùn)行下去,只有被移除動(dòng)畫(huà)才能結(jié)束
1.代碼
@Composable fun rememberInfiniteTransition1() { val infiniteTransition = rememberInfiniteTransition() val color by infiniteTransition.animateColor( initialValue = Color.Red, targetValue = Color.Green, animationSpec = infiniteRepeatable( animation = tween(1000, easing = LinearEasing), repeatMode = RepeatMode.Reverse ) ) Box(Modifier.fillMaxSize(1f), contentAlignment = Alignment.Center) { Box( Modifier .fillMaxSize(0.8f) .background(color), contentAlignment = Alignment.Center ) { Text( text = "公眾號(hào):安安安安卓 原創(chuàng),禁抄襲", style = TextStyle(color = Color.White, fontSize = 30.sp) ) } } }
2.效果
TargetBasedAnimation 可以控制動(dòng)畫(huà)的執(zhí)行時(shí)間,還可以延遲一段時(shí)間再開(kāi)啟動(dòng)畫(huà)。
1.代碼
@Composable fun animTargetBasedAnimation() { var state by remember { mutableStateOf(0) } val anim = remember { TargetBasedAnimation( animationSpec = tween(2000), typeConverter = Float.VectorConverter, initialValue = 100f, targetValue = 300f ) } var playTime by remember { mutableStateOf(0L) } var animationValue by remember { mutableStateOf(0) } LaunchedEffect(state) { val startTime = withFrameNanos { it } println("進(jìn)入?yún)f(xié)程:") do { playTime = withFrameNanos { it } - startTime animationValue = anim.getValueFromNanos(playTime).toInt() } while (!anim.isFinishedFromNanos(playTime)) } Box(modifier = Modifier.fillMaxSize(1f),contentAlignment = Alignment.Center) { Box(modifier = Modifier .size(animationValue.dp) .background(Color.Red,shape = RoundedCornerShape(animationValue/5)) .clickable { state++ },contentAlignment = Alignment.Center) { Text(text = animationValue.toString(),style = TextStyle(color = Color.White,fontSize = (animationValue/5).sp)) } } }
2.效果
AnimationSpec 可以自定義動(dòng)畫(huà)的行為,效果類似于原生動(dòng)畫(huà)中的估值器。
SpringSpec 彈簧效果
1.代碼
@Composable fun animSpring() { val state = remember { mutableStateOf(true) } var value = animateIntAsState( targetValue = if (state.value) 300 else 100, animationSpec = spring( dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessVeryLow ) ) Box( Modifier .fillMaxSize(1f) .padding(start = 30.dp), contentAlignment = Alignment.CenterStart ) { Box( Modifier .width(value.value.dp) .height(80.dp) .background(Color.Red, RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp)) .clickable { state.value = !state.value }, contentAlignment = Alignment.CenterStart ) { Text(text = "哈哈哈", style = TextStyle(color = Color.White, fontSize = 20.sp)) } } }
2.效果
TweenSpec 動(dòng)畫(huà)時(shí)間可控
1.代碼
@Composable fun animTweenSpec() { val state = remember { mutableStateOf(true) } val value = animateIntAsState( targetValue = if (state.value) 300 else 100, animationSpec = tween( durationMillis = 1500, delayMillis = 200, easing = LinearEasing ) ) Box( Modifier .fillMaxSize(1f) .padding(start = 50.dp), contentAlignment = Alignment.CenterStart ) { Box( Modifier .width(value.value.dp) .height(100.dp) .background(Color.Red, RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp)) .clickable { state.value = !state.value } ) { } } }
2.效果
FrameSpec
1.代碼
@Composable fun animkeyframesSpec() { var state by remember { mutableStateOf(true) } val value by animateIntAsState( targetValue = if (state) 300 else 100, animationSpec = keyframes { durationMillis = 2000 0 at 700 with LinearOutSlowInEasing 700 at 1400 with FastOutLinearInEasing 1400 at 2000 }) Box(Modifier.fillMaxSize(1f), contentAlignment = Alignment.CenterStart) { Box( Modifier .width(value.dp) .height(100.dp) .background(Color.Red, RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp)) .clickable { state = !state } ) { } } }
2.效果
RepeatableSpec 實(shí)現(xiàn)有限次數(shù)的重復(fù)動(dòng)畫(huà)
執(zhí)行有限次數(shù)動(dòng)畫(huà)后自動(dòng)停止
1.代碼
@Composable fun animrepeatableSpec() { var state by remember { mutableStateOf(true) } val value by animateIntAsState( targetValue = if (state) 300 else 100, animationSpec = repeatable( iterations = 5,//動(dòng)畫(huà)重復(fù)執(zhí)行的次數(shù),設(shè)置多少就執(zhí)行多少次 animation = tween(durationMillis = 1000), repeatMode = RepeatMode.Reverse ) ) Box( Modifier .fillMaxSize(1f) .padding(start = 30.dp), contentAlignment = Alignment.CenterStart) { Box( Modifier .width(value.dp) .height(100.dp) .background(Color.Red, RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp)) .clickable { state = !state } ) { } } }
2.效果
代碼中設(shè)置了重復(fù) 5 次,所以反復(fù)執(zhí)行五次后動(dòng)畫(huà)結(jié)束
InfiniteRepeatableSpec 無(wú)限次數(shù)執(zhí)行動(dòng)畫(huà)
動(dòng)畫(huà)會(huì)無(wú)限次的執(zhí)行下去,直到視圖被移除
1.代碼
@Composable fun animinfiniteRepeatableSpec() { var state by remember { mutableStateOf(true) } val value by animateIntAsState( targetValue = if (state) 300 else 100, animationSpec = infiniteRepeatable( animation = tween(durationMillis = 1000), repeatMode = RepeatMode.Reverse ) ) Box( Modifier .fillMaxSize(1f) .padding(start = 30.dp), contentAlignment = Alignment.CenterStart) { Box( Modifier .width(value.dp) .height(100.dp) .background(Color.Red, RoundedCornerShape(topEnd = 30.dp, bottomEnd = 30.dp)) .clickable { state = !state } ) { Text(text = "公眾號(hào):安安安安卓 原創(chuàng),禁轉(zhuǎn)載") } } }
2.效果
Easing 類似于我們?cè)鷦?dòng)畫(huà)中的差值器
有以下幾種選擇:
FastOutSlowInEasing
LinearOutSlowInEasing
FastOutLinearInEasing
LinearEasing
CubicBezierEasing
這幾種實(shí)現(xiàn)的效果和 android 原生實(shí)現(xiàn)的動(dòng)畫(huà)差值器差距很大,甚至看不出有啥效果,所以代碼我就不放了。有清楚原因的讀者可以聯(lián)系我
實(shí)現(xiàn)效果:
大多數(shù) Compose 動(dòng)畫(huà) API 都支持將 Float、Color、Dp 以及其他基本數(shù)據(jù)類型作為開(kāi)箱即用的動(dòng)畫(huà)值,但有時(shí)我們需要為其他數(shù)據(jù)類型(包括我們的自定義類型)添加動(dòng)畫(huà)效果
本例中實(shí)現(xiàn)顏色和大小的變換動(dòng)畫(huà)
代碼中我們定義了一個(gè) AnimSize 類,類中的第一個(gè)參數(shù)是顏色數(shù)據(jù),第二個(gè)參數(shù)是尺寸數(shù)據(jù)。動(dòng)畫(huà)執(zhí)行過(guò)程中會(huì)同事改變顏色和控件尺寸效果。
1.代碼
@Composable fun animAnimationVector() { var state by remember { mutableStateOf(true) } val value by animateValueAsState( targetValue = if (state) AnimSize(0xffff5500, 100f) else AnimSize(0xff00ff00, 300f), typeConverter = TwoWayConverter( convertToVector = { // AnimationVector2D(target.color.toFloat(), target.size) AnimationVector2D(it.color.toFloat(), it.size) }, convertFromVector = { AnimSize(it.v1.toLong(), it.v2) } ) ) println("顏色:${value.color}") Box(modifier = Modifier.fillMaxSize(1f).padding(30.dp), contentAlignment = Alignment.Center) { Box( modifier = Modifier .size(value.size.dp) // .size(300.dp) .background(Color(value.color), RoundedCornerShape(30.dp)) .clickable { state = !state } ) { } } } data class AnimSize(val color: Long, val size: Float)
2.效果
缺點(diǎn)是執(zhí)行顏色變化過(guò)程中有閃爍
高級(jí)動(dòng)畫(huà)一般指封裝性較高的動(dòng)畫(huà),使用較為簡(jiǎn)單,主要有以下三種:
因高級(jí)動(dòng)畫(huà)效果不明顯,gif 很難展現(xiàn)出效果,所以這里不放代碼和效果圖了
AnimatedVisibility
animateContentSize
Crossfade
關(guān)于“Jetpack Compose怎么實(shí)現(xiàn)動(dòng)畫(huà)效果”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。