日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Jetpack?Compose慣性衰減動畫AnimateDecay詳解_Android

作者:vivo祁同偉 ? 更新時間: 2022-12-04 編程語言

什么是慣性衰減動畫

比如說我們玩微信的時候 手指一拉,微信的列表就會慣性滑動 ,這個滑動的速率當然是越來越慢的,最終停止, 這個其實就是慣性衰減動畫的典型例子

那這個例子和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開頭的函數,還有一個沒有?

我們先看那個有的

這里其實是會根據屏幕像素密度的變化而變化的,所以這個值是一個可變的,為了響應這個變化 所以系統默認的給我們提供了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)) {
        }
    }
}

原文鏈接:https://juejin.cn/post/7160653354287235086

欄目分類
最近更新