Transition 初体验

先看下面这个代码 ,其实作用很简答 便是一个点击时刻 触发一段动画罢了

一边改size 一边改圆角巨细

setContent {
    var big by remember {
        mutableStateOf(false)
    }
    var bigTransition = updateTransition(big, label = "big")
    //animateDpAsState
    val size by bigTransition.animateDp(label = "size") {
        if (it) 100.dp else 50.dp
    }
    val corner by bigTransition.animateDp(label = "corner") {
        if (it) 50.dp else 0.dp
    }
    Box(modifier = Modifier
        .size(size)
        .clip(RoundedCornerShape(corner))
        .background(Color.Green)
        .clickable {
            big = !big
        })
}

有人就要问了 你这个动画作用 咱们用animateDpAsState 相同能够完成啊,代码还比你这个少一点,为啥要用这个?

咱们能够看看 假如用animateDpAsState 来写 代码是啥相同的

setContent {
    var big by remember {
        mutableStateOf(false)
    }
    val size by animateDpAsState (
        if (big) 100.dp else 50.dp
    )
    val corner by animateDpAsState (
        if (big) 0.dp else 50.dp
    )
    Box(modifier = Modifier
        .size(size)
        .clip(RoundedCornerShape(corner))
        .background(Color.Green)
        .clickable {
            big = !big
        })
}

显着看的出来 animateDpAsState 写法反而更简略。

两者差异或者说为啥要推 Transition 这个东西?

首要第一, 当你想做多个动画的时候,比方上文中的例子,我要改动多个状况,animateDpAsState 这一个函数就代表了一个协程, 你有10个状况要改动 那便是10个, 可是假如用Transition 来办理,则不管你有多少个状况需要改动,则都只要一个协程,性能上 Transition 会有一点优势

第二 Transition 能够更好的预览作用

看下图 几个红框的地方 其实便是Transition 写法中的label, 这种预览方法能够很便利的让咱们调试动画作用 这是animateDpAsState 没有的

Jetpack Compose - Transition动画 (十)

第三 当你办理一组动画的时候,实际上 Transition 的写法 更好,这点纯属个人代码审美了

AnimatedVisibility

来看下这个动画,看名字也能知道 这应该是个操控可见性的动画

setContent {
    Column() {
        var show by remember {
            mutableStateOf(true)
        }
        AnimatedVisibility(show) {
            Box(
                modifier = Modifier
                    .height(100.dp)
                    .width(100.dp)
                    .background(color = Color.Red)
            )
        }
        Button(onClick = {
            show = !show
        },) {
           Text(text = "change") 
        }
    }
}

能够看下作用

Jetpack Compose - Transition动画 (十)

你会发现,这个可见性动画有点神奇啊,他的表现形式 是垂直方向弹性,跟咱们的布局Column是一一对应的

来看下代码 就一目了然了

Jetpack Compose - Transition动画 (十)

相同咱们也看一下其他的完成

Jetpack Compose - Transition动画 (十)

看到这 咱们其实能够下一个定论 便是 AnimatedVisibility 本质上便是 Transition 动画

能够着重关注下 下面的 动画是怎样完成的?+ 号啥意思

Jetpack Compose - Transition动画 (十)

首要便是这个sealed class了, 不知道sealed class的同学 能够自己搜下, 暂时了解成他便是一个interface即可

Jetpack Compose - Transition动画 (十)

这儿能够看下他的完成就只要一个impl罢了

Jetpack Compose - Transition动画 (十)

Jetpack Compose - Transition动画 (十)

恩,实际上动画的表现形式便是在这个class中来决议了

Jetpack Compose - Transition动画 (十)

fade 其实便是一个 淡入淡出的作用 能够看下参数类型

Jetpack Compose - Transition动画 (十)

再看下这个slide 他其实便是定义你这个收支的作用 是从哪个方位延伸而来,属所以延伸动画

AnimatedVisibility(show, enter = slideIn(tween(2500)) {
    IntOffset(-50,-50)
}) {
    Box(
        modifier = Modifier
            .height(100.dp)
            .width(100.dp)
            .background(color = Color.Red)
    )
}

这个lambda参数 便是定义 你是从哪个方位 扩展而来

能够看下作用

Jetpack Compose - Transition动画 (十)

这儿或许有人觉得 你这个作用太傻了,正常人不会写的这么丑 我想要的是 跟我的view 自己巨细相关的

其实这个动画是有个默认值能够取到原始巨细的

Jetpack Compose - Transition动画 (十)

所以咱们能直接取到view的宽高 那么全部就很和谐了

略微改一下

IntOffset(-it.width,-it.height)

作用我们能够自己跑一下 看看,这儿就不重复演示了

再来看一下 第三个参数ChangeSize

Jetpack Compose - Transition动画 (十)

AnimatedVisibility(show, enter = expandIn(tween(2500), expandFrom = Alignment.TopStart,
    initialSize = { IntSize(0, 0) })) {
    Box(
        modifier = Modifier
            .height(100.dp)
            .width(100.dp)
            .background(color = Color.Red)
    )
}

看下作用:

Jetpack Compose - Transition动画 (十)

这儿或许有人会问,这个作用和slidein 有点相似?有啥差异?

其实差异大了啊,这个changesize 本质上是 裁切变换的view的巨细,你看这个change的方位就能看出来 他是逐步到下面的

而咱们的slideIn,也便是slide动画 他的巨细是一会儿就固定到view的原始巨细,然后view从一个方位 挪过来罢了。

这俩本质上不是一个东西,仅仅视觉上的作用比较相似罢了

最后一个参数 Scale 挺简略的,我们自己写一个试试吧,留意Scale 也是不改动view巨细的,改动的仅仅view绘制的那部分巨细。

+ 号是怎样回事?

Jetpack Compose - Transition动画 (十)

Jetpack Compose - Transition动画 (十)

其实要害便是在plus函数的完成了, 咱们能够简略的了解为 A+B 就等于 A.plus(B)

仔细看这个 plus函数的完成 其实便是 假如A有 那就用A的,假如A没有 就用B的

组合,留意是组合不是相加,然后 组合成一个新的TransitionData

CrossFade

setContent {
    Column() {
        var show by remember {
            mutableStateOf(true)
        }
        Crossfade(show){
            if (it) {
                Box(
                    modifier = Modifier
                        .height(50.dp)
                        .width(50.dp)
                        .background(color = Color.Blue)
                )
            } else {
                Box(
                    modifier = Modifier
                        .height(100.dp)
                        .width(100.dp)
                        .background(color = Color.Red)
                )
            }
        }
        Button(
            onClick = {
                show = !show
            },
        ) {
            Text(text = "change")
        }
    }
}

这个很简略,其实便是2个view的改变 改变的过程中有动画

参数和上一个小节里边简直一摸相同,不过多介绍了

AnimatedContent

这个东西和crossfade 作用差不多 能够操控多个view展现的,只不过他操控的粒度更细致。

setContent {
    Column() {
        var show by remember {
            mutableStateOf(true)
        }
        AnimatedContent(show) {
            if (it) {
                Box(
                    modifier = Modifier
                        .background(Color.Red)
                        .width(100.dp)
                        .height(100.dp)
                )
            } else {
                Box(
                    modifier = Modifier
                        .background(Color.Green)
                        .width(50.dp)
                        .height(50.dp)
                )
            }
        }
        Button(
            onClick = {
                show = !show
            },
        ) {
            Text(text = "AnimatedContent change")
        }
        var show2 by remember {
            mutableStateOf(true)
        }
        Crossfade(show2, modifier = Modifier.padding(top = 100.dp)) {
            if (it) {
                Box(
                    modifier = Modifier
                        .background(Color.Red)
                        .width(100.dp)
                        .height(100.dp)
                )
            } else {
                Box(
                    modifier = Modifier
                        .background(Color.Green)
                        .width(50.dp)
                        .height(50.dp)
                )
            }
        }
        Button(
            onClick = {
                show2 = !show2
            },
        ) {
            Text(text = "Crossfade change2")
        }
    }
}

Jetpack Compose - Transition动画 (十)

能够看下 animatedContent和crossfade的差异

  1. crossfade 两个一起改变,进入和退出的动画是一起进行,而animatedContent则是有先后顺序 简略来说cf 是并行的,而animatecontent则是串行的

  2. AnimateContent的 size改变是 动态的,逐渐改变的,而Crossfade 则是突兀的,瞬间改变的

我们能够多领会一下gif图 或者自己写个demo

能够看下代码 显着的deley时刻和 fadeout的动画时刻是一一对应的

Jetpack Compose - Transition动画 (十)

能够看下这个要害参数 contenttransform

Jetpack Compose - Transition动画 (十)

这个target和init 2个参数便是 进入和退出的作用,很简略, sizeTransform 是 巨细的突变作用 而 targetContentZIndex 则是 z轴的优先级,也便是 到底是你隐瞒我还是我隐瞒你

不过 一般咱们写动画也不会写到这个targetContentZIndex

所以把握了这些参数信息 你很容易就能够定制自己想要的动画作用了

比方下面这种写法,便是等一个动画完毕了 别的一个动画才开端 很简略的写法

AnimatedContent(show, transitionSpec = { fadeIn(tween(3000)) with fadeOut(tween(3000,3000)) }) {

总结

整个Compose的动画 到这儿就差不多完毕了,全体感觉上写法比传统view 上 要简略不少,多写几个demo 试试不同参数的作用 也就能快速把握了。别的引荐下扔物线大佬的compose课 讲的很好