網站首頁 編程語言 正文
本篇主要是自定義動畫與Animatable
。
AnimationSpec
上一篇中,出現了多次animationSpec
屬性,它是用來自定義動畫規范的。例如:
fun Modifier.animateContentSize( animationSpec: FiniteAnimationSpec<IntSize> = spring(), finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)? = null ): Modifier
下面是幾種自帶的動畫規范:
1.spring
我們上一篇也簡單說到了,它是一種彈性動畫。源碼如下:
@Stable fun <T> spring( dampingRatio: Float = Spring.DampingRatioNoBouncy, stiffness: Float = Spring.StiffnessMedium, visibilityThreshold: T? = null ): SpringSpec<T> = SpringSpec(dampingRatio, stiffness, visibilityThreshold)
dampingRatio
: 定義彈簧的彈性,數值越小彈性越高。默認值DampingRatioNoBouncy
為1f。下圖為其他數值的效果:
-
stiffness
: 定義彈簧向結束值移動的速度。默認值StiffnessMedium
為1500f。 -
visibilityThreshold
:可見臨界值(動畫停止的值)。比如目標150dp,此值設置10dp,那么回彈距離小于這個值時就會停止彈性效果。
2.tween
在指定的時間內使用緩和曲線在起始值和結束值之間添加動畫效果。
@Stable fun <T> tween( durationMillis: Int = DefaultDurationMillis, delayMillis: Int = 0, easing: Easing = FastOutSlowInEasing ): TweenSpec<T> = TweenSpec(durationMillis, delayMillis, easing) val FastOutSlowInEasing: Easing = CubicBezierEasing(0.4f, 0.0f, 0.2f, 1.0f)
-
durationMillis
:動畫的持續時間,默認值300毫秒。 -
delayMillis
:延遲動畫開始的時間。 -
easing
:兩個值之間的插值曲線,類似Android中的Interpolator
插值器。目前compose中提供了五種類型,這里就不一一說明了,實際使用時可以嘗試一下。當然你也可以使用CubicBezierEasing
甚至Easing
自定義曲線。
3.keyframes
在動畫時長內的不同時間戳中指定快照值,實現動畫效果。在任何給定時間,動畫值都將插值到兩個關鍵幀值之間。對于其中每個關鍵幀,您都可以指定 Easing
來確定插值曲線。
@Stable fun <T> keyframes( init: KeyframesSpec.KeyframesSpecConfig<T>.() -> Unit ): KeyframesSpec<T> { return KeyframesSpec(KeyframesSpec.KeyframesSpecConfig<T>().apply(init)) }
例子:
val value by animateFloatAsState( targetValue = 1f, animationSpec = keyframes { durationMillis = 375 0.0f at 0 with LinearOutSlowInEasing // for 0-15 ms 0.2f at 15 with FastOutLinearInEasing // for 15-75 ms 0.4f at 75 // ms 0.4f at 225 // ms } )
解釋一下上面的例子:整體起始值0和結束值1,動畫時長375毫秒。
- 從0開始到0.2結束,前15毫秒使用
LinearOutSlowInEasing
過渡。 - 從0.2開始到0.4結束,15到75毫秒使用
FastOutLinearInEasing
過渡。 - 從0.4開始到0.4結束,75到225毫秒勻速過渡。(靜止效果)
- 從0.4開始到1結束,225毫秒到結束勻速過渡。
效果圖如下:
keyframes
同樣也可以設置delayMillis
指定延時時間。
4.repeatable
重復運行基于時長的動畫,直至達到指定的迭代計數。
@Stable fun <T> repeatable( iterations: Int, animation: DurationBasedAnimationSpec<T>, repeatMode: RepeatMode = RepeatMode.Restart, initialStartOffset: StartOffset = StartOffset(0) ): RepeatableSpec<T> = RepeatableSpec(iterations, animation, repeatMode, initialStartOffset)
-
iterations
,動畫運行的次數。1表示不重復。建議使用infiniteRepeatable創建無限重復的動畫。 -
animation
,設置需要重復的動畫。 -
repeatMode
,重復模式。指定動畫是從頭開始 (RepeatMode.Restart) 還是從結尾開始 (RepeatMode.Reverse) 重復播放。 -
initialStartOffset
,可用于延遲動畫的開始或快進動畫到給定的播放時間。如果設置StartOffset(1500)
就是延遲動畫。 設置StartOffset(1500, offsetType = StartOffsetType.FastForward)
就是快進動畫。默認情況下,延時時長為0。
如果需要動畫重復無限次,可以使用infiniteRepeatable
,用法與repeatable
一致。
5.snap
snap
是特殊的 AnimationSpec
,它會立即將值切換到結束值。您可以指定 delayMillis 來延遲動畫播放的開始時間。
@Stable fun <T> snap(delayMillis: Int = 0) = SnapSpec<T>(delayMillis)
Animatable
Animatable
是一個值容器,它可以在通過 animateTo
更改值時為值添加動畫效果。它可確保一致的連續性和互斥性,這意味著值變化始終是連續的,并且會取消任何正在播放的動畫。
Animatable
的許多功能(包括 animateTo)以掛起函數的形式提供。這意味著,它們需要封裝在適當的協程作用域內。例如,您可以使用 LaunchedEffect
可組合項針對指定鍵值的時長創建一個作用域。
// Start out gray and animate to green/red based on `ok` val color = remember { Animatable(Color.Gray) } LaunchedEffect(ok) { color.animateTo(if (ok) Color.Green else Color.Red) } Box(Modifier.fillMaxSize().background(color.value))
在上面的示例中,我們創建并記住了初始值為 Color.Gray
的 Animatable
實例。根據布爾標記 ok
的值,顏色將以動畫形式呈現 Color.Green
或 Color.Red
。對該布爾值的任何后續更改都會使動畫開始使用另一種顏色。如果更改該值時有正在播放的動畫,系統會取消該動畫,并且新動畫將以當前速度從當前快照值開始播放。
與 animate*AsState
相比,使用 Animatable
可以直接對以下幾個方面進行更精細的控制。首先,Animatable
的初始值可以與第一個目標值不同。例如,上面的代碼示例首先顯示一個灰色框,然后立即開始通過動畫呈現為綠色或紅色。其次,Animatable
對內容值提供更多操作(即 snapTo
和 animateDecay
)。snapTo
可立即將當前值設為目標值。如果動畫本身不是唯一的可信來源,且必須與其他狀態(如觸摸事件)同步,該函數就非常有用。animateDecay
用于啟動播放從給定速度變慢的動畫(衰減)。這有助于實現投擲行為。
下面看一個官方demo:
Column(modifier = Modifier.fillMaxWidth()) { // Creates an `Animatable` to animate Offset and `remember` it. val animatedOffset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) } Box( Modifier.fillMaxSize().background(Color(0xffb99aff)).pointerInput(Unit) { coroutineScope { while (true) { val offset = awaitPointerEventScope { awaitFirstDown().position } // Launch a new coroutine for animation so the touch detection thread is not // blocked. launch { // Animates to the pressed position, with the given animation spec. animatedOffset.animateTo( offset, animationSpec = spring(stiffness = Spring.StiffnessLow) ) } } } } ) { Text("Tap anywhere", Modifier.align(Alignment.Center)) Box( Modifier .offset { // Use the animated offset as the offset of the Box. IntOffset( animatedOffset.value.x.roundToInt(), animatedOffset.value.y.roundToInt() ) } .size(40.dp) .background(Color(0xff3c1361), CircleShape) ) } }
效果圖這里我就不放了。就是頁面上有個40*40dp的圓形view,點擊屏幕任意位置,他就會移動過去。這里核心靠的就是animateTo
方法,而且無論我們中間如果快速點擊不同位置,系統會取消上一個動畫,接著當前位置移動到目標位置。
從上面這張圖可以看出各個API之間的關系。所有這些 API 都基于更基礎的 Animation
API。雖然大多數應用不會直接使用 Animation
,但 Animation
的某些自定義功能可以通過更高級別的 API 獲得。
到此,Compose的動畫部分大體結束。
參考
Compose官方文檔
Compose官方文檔 – Animatable
原文鏈接:https://weilu.blog.csdn.net/article/details/125997035
相關推薦
- 2023-03-05 Kotlin協程低級api?startCoroutine與ContinuationIntercept
- 2022-03-14 YUV420SP to JPEG
- 2023-01-13 Matlab中的mat數據轉成python中使用的npy數據遇到的坑及解決_python
- 2023-02-02 C#實現網絡小程序的步驟詳解_C#教程
- 2022-03-15 pycharm安裝opencv出現錯誤:Could not find a version that
- 2024-03-08 SpringBoot開發中VO、DTO的作用,以及使用場景
- 2022-03-18 .Net使用分表分庫框架ShardingCore實現多字段分片_實用技巧
- 2022-11-22 python枚舉類型定義與使用講解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支