什么是惯性衰减动画

比如说咱们玩微信的时分 手指一拉,微信的列表就会惯性滑动 ,这个滑动的速率当然是越来越慢的,终究中止, 这个其实便是惯性衰减动画的典型比如

那这个比如和animateTo 有啥区别呢? 一个速率变慢的动画 ,听起来似乎 咱们用animateTo 设置一些参数也能够完结

其实这儿最大的区别便是 animateTo 你是需求设置目标值的,也便是动画完毕的那一刻 某个view特点的值 你必须清晰指定

而所谓的惯性衰减动画 animateDecay 则不需求指定

animateDecay: 从初始速度渐渐停下来 例如松手之后的惯性滑动

animateTo: 指定完毕的特点值

看个小比如,来感受一下 模拟的 惯性滑动作用

下面的代码便是以1000.dp的初始速度 开端做惯性动画,直到停下

 setContent {
            val anim = remember {
                Animatable(0.dp, Dp.VectorConverter)
            }
            val re = rememberSplineBasedDecay<Dp>()
            LaunchedEffect(Unit) {
                delay(1000)
//                exponentialDecay<>()
//                splineBasedDecay<>()  android的默许惯性滑动曲线算法 listview rv gridview 之类的 和传统view的overScroller 是一个意思
//                rememberSplineBasedDecay() 一般就用待remember的就能够 不带的能够不用
                // 这个第一个1000.dp 的参数 代表初始速度  留意这个速度是物理像素值 而不是所谓的速度
                // 所以这个值 越大,这个Box的位移 偏移量就越大,能够修正这个值今后感受一下
                anim.animateDecay(1000.dp,re)
            }
            Box(
                Modifier
                    .padding(0.dp, anim.value, 0.dp, 0.dp)
                    .size(100.dp)
                    .background(Color.Green)) {
            }
        }

留意 splineBasedDecay 一般只能用于 像素的改变,由于这个东西能够针对不同像素密度的设备而改变

exponentialDecay 这个便是典型的不会根据像素密度改变而改变,比如色彩,角度之类的

setContent {
    val anim = remember {
        Animatable(0.dp, Dp.VectorConverter)
    }
    // frictionMultiplier 代表摩擦力系数  这个值越大 改变的速度就越快 终究反应的便是 这个box的位移越小
    // absVelocityThreshold 速度阈值 大概意思便是 到这个阈值了 就中止了 一般而言 这2个参数 都能够不用设置 默许就好
    val decay = exponentialDecay<Dp>(3f,0.5f)
    LaunchedEffect(Unit) {
        delay(1000)
        anim.animateDecay(1000.dp,decay)
    }
    Box(
        Modifier
            .padding(0.dp, anim.value, 0.dp, 0.dp)
            .size(100.dp)
            .background(Color.Green)) {
    }
}

惯性衰减动画 使用要点

上述的代码或许有人要问,为啥你有2个decay,其中一个用的时分有remember开头的函数,还有一个没有?

咱们先看那个有的

Jetpack Compose - 惯性衰减动画AnimateDecay(八)

这儿其实是会根据屏幕像素密度的改变而改变的,所以这个值是一个可变的,为了呼应这个改变 所以体系默许的给咱们供给了remember的这个函数

而 exponentialDecay 则由于不会呼应体系的改变,所以不需求,能够直接用,可是 你要是真的直接用了,那就错了 由于 你直接用 那就每次compose页面刷新的时分 他都会初始化一下这个值,这个很没有必要,而且许多时分会出错,所以最佳的做法 仍是要remember一下

val decay = remember {
    exponentialDecay<Dp>(3f,0.5f)
}

block 监听

有时 咱们使用动画时,会对某一个view使用动画,其他view 呼应这个动画的改变 而改变即可,讲白了便是要监听动画的改变,相同的在 compose中 也供给了block这个lambda 能够协助咱们完结相似的作业

他是监听动画改变的每一帧,给出对应的回调

如下面的比如所示,这个便是 绿色的box在位移动画,而 黑色的box 跟着绿色的一起改变

setContent {
    val anim = remember {
        Animatable(0.dp, Dp.VectorConverter)
    }
    // 咱们第二个box 就用这个来代表位移吧
    var paddingTop  by remember {
        mutableStateOf(anim.value)
    }
    val decay = remember {
        exponentialDecay<Dp>(2f)
    }
    LaunchedEffect(Unit) {
        delay(1000)
        // 动画的监听
        anim.animateDecay(1000.dp, decay) {
            paddingTop = value
        }
    }
    Row() {
        Box(
            Modifier
                .padding(0.dp, anim.value, 0.dp, 0.dp)
                .size(100.dp)
                .background(Color.Green)) {
        }
        Box(
            Modifier
                .padding(0.dp, paddingTop, 0.dp, 0.dp)
                .size(100.dp)
                .background(Color.Black)) {
        }
    }
}