Jetpack Compose - 慣性衰減動畫AnimateDecay(八)
什麼是慣性衰減動畫
比如說我們玩微信的時候 手指一拉,微信的列表就會慣性滑動 ,這個滑動的速率當然是越來越慢的,最終停止, 這個其實就是慣性衰減動畫的典型例子
那這個例子和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)) {
}
}
} ```
- Jetpack Compose - Effect與協程 (十五)
- 谷歌的bug:當 CompileSdk 33 遇上Kotlin
- Jetpack Compose - DrawModifier (十三)
- Jetpack Compose - Transition動畫 (十)
- Jetpack Compose - 慣性衰減動畫AnimateDecay(八)
- Jetpack Compose - AnimationSpec (七)
- Jetpack Compose - Animatable與animateAsState (六)
- Jetpack Compose - 淺談 CompositionLocal (五)
- ASM 修改位元組碼 引發的R8 編譯報錯
- Go語言 基於gin框架從0開始構建一個bbs server(二)-使用者登入
- Go語言 基於gin定義一個簡單的web server 開發框架(三)
- Go語言 基於gin定義一個簡單的web server 開發框架(二)
- Go語言 viper與web服務的關機,重啟
- Go語言 zap日誌系統與gin繼承
- Go語言 go-redis與watch
- Go 語言 MySql 基本操作
- Go 語言 常用標準庫 介紹
- Go語言 併發-select 與 鎖
- Go語言 併發-Channel
- Go語言 錯誤處理以及資源管理