Animatable
与animation-core-android中有相同名字的API,此处是单纯的Color类型的动画
val a = remember { Animatable(Color.Red) }
val scope = rememberCoroutineScope()
Box(modifier = Modifier.background(a.value).size(100.dp)) {
Text("Hello")
}
Button(onClick = {
scope.launch {
a.animateTo(if(a.value == Color.Red) Color.Blue else Color.Red, tween(1000))
a.snapTo(if(a.value == Color.Red) Color.Blue else Color.Red) // 瞬间切换, 无动画
}
}) {
Text("Change Color")
}
EnterTransition、ExitTransition
入场动画和出场动画。以下都是成对的,EnterTransition对应ExitTransition(只有expand例外,没有提供expandOut,expand对应的是shrink)
//渐显渐隐
fadeIn(animationSpec = tween(5000), initialAlpha = 0f)
fadeOut(animationSpec = tween(5000), targetAlpha = 0f)
//缩放进入和缩放退出
scaleIn(animationSpec = tween(5000), initialScale = 0.5f, transformOrigin = TransformOrigin.Center)
scaleOut(animationSpec = tween(5000), targetScale = 0.5f, transformOrigin = TransformOrigin.Center)
//水平和垂直同时增长
expandIn { size ->
//size是最终的尺寸,也就是当前元素会扩展到的尺寸
IntSize(size.width/2,size.height/2) //初始为一半大小
}
expandHorizontally { finalWidth ->
//横向向右展开
finalWidth/2 //初始宽度为一半
}
expandVertically { finalHeight ->
//卷帘门效果,纵向向下展开
finalHeight/2 //初始高度为一半
}
shrinkOut(animationSpec = tween(2000)) {
// it: IntSize,为当前元素的尺寸
IntSize(20,20) //缩小到20x20时消失,完成退出动画
}
shrinkHorizontally (animationSpec = tween(2000)) {
// it: Int,为当前元素的宽度
20 //缩小到20时消失,完成退出动画
}
shrinkVertically (animationSpec = tween(2000)) {
// it: Int,为当前元素的高度
20 //缩小到20时消失,完成退出动画
}
//平移进入和平移退出
slideIn { size ->
//size是容器的尺寸
IntOffset(size.width,size.height) //从右下角向左上角滑入
}
slideOut { size ->
//size是容器的尺寸
IntOffset(size.width,size.height) //从当前位置向右下角滑出
}
//水平平移进入和水平平移退出
slideInHorizontally(animationSpec = tween(2000)) {
it //it是容器的宽度,直接返回也就是从右边向左滑入
}
slideOutHorizontally(animationSpec = tween(2000)) {
it //it是容器的宽度,直接返回也就是从当前位置向右滑出边界
}
//垂直平移进入和垂直平移退出
slideInVertically {
it //it是容器的高度,直接返回也就是从下边向上滑入
}
slideOutVertically {
it //it是容器的高度,直接返回也就是从当前位置向下滑出边界
}
//不使用动画
EnterTransition.None
ExitTransition.None
//动画相加
slideInHorizontally(animationSpec = tween(2000)) {
it
} + fadeIn(tween(5000))
元素:Crossfade
一个带交叉切换效果的元素
//元素函数签名
fun <T> Crossfade(
targetState: T,
modifier: Modifier = Modifier,
animationSpec: FiniteAnimationSpec<Float> = tween(),
label: String = "Crossfade",
content: @Composable (T) -> Unit
)
var currentPage by remember { mutableStateOf("Page1") }
Column {
Button(onClick = { currentPage = if (currentPage == "Page1") "Page2" else "Page1" }) {
Text("Toggle Page")
}
Crossfade (targetState = currentPage, label = "") { page:String ->
when (page) {
"Page1" -> Box(modifier = Modifier.fillMaxSize().background(Color.Red)) {
Text("哈哈")
}
"Page2" -> Box(modifier = Modifier.fillMaxSize().background(Color.Blue)) {
Text("我是第二个page2")
}
}
}
}
元素:AnimatedVisibility
一个用State控制显示的元素,可在参数中传递退出和进入的动画。
动画函数的lamda内的参数获取到的大小或宽高都是内容区域的宽高
下面的shrinkOut函数中的it是IntSize类型,值为700*1400(px),就是200*400dp
//签名1:
fun AnimatedVisibility(
visibleState: MutableTransitionState<Boolean>,
modifier: Modifier = Modifier,
enter: EnterTransition = fadeIn() + expandIn(),
exit: ExitTransition = fadeOut() + shrinkOut(),
label: String = "AnimatedVisibility",
content: @Composable() AnimatedVisibilityScope.() -> Unit
)
签名2:
fun AnimatedVisibility(
visible: Boolean,
modifier: Modifier = Modifier,
enter: EnterTransition = fadeIn() + expandIn(),
exit: ExitTransition = shrinkOut() + fadeOut(),
label: String = "AnimatedVisibility",
content: @Composable() AnimatedVisibilityScope.() -> Unit
)
var visible by remember { mutableStateOf(false) }
Column {
Button(onClick = { visible = !visible }) {
Text("Toggle Visibility")
}
AnimatedVisibility(
visible = visible,
enter = fadeIn(animationSpec = tween(2000)),
exit = shrinkOut (animationSpec = tween(2000)) {
it/ 2
}
) {
Column {
Box(modifier = Modifier.size(200.dp).background(Color.Red))
Box(modifier = Modifier.size(200.dp).background(Color.Blue))
}
}
}