欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android Compose 屬性動(dòng)畫使用探索詳解

 更新時(shí)間:2022年09月27日 14:54:37   作者:loongwind  
這篇文章主要為大家介紹了Android Compose 屬性動(dòng)畫使用探索詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

Jetpack Compose(簡(jiǎn)稱 Compose )是 Google 官方推出的基于 Kotlin 語(yǔ)言的 Android 新一代 UI 開發(fā)框架,其采用聲明式的 UI 編程特性使得 Android 應(yīng)用界面的編寫和維護(hù)變得更加簡(jiǎn)單。

本專欄將詳細(xì)介紹在使用 Compose 進(jìn)行 UI 開發(fā)中如何實(shí)現(xiàn)炫酷的動(dòng)畫效果。動(dòng)畫效果在 App 使用中至關(guān)重要,它使得 App 的交互更加自然流暢,用戶使用體驗(yàn)更加良好。

在傳統(tǒng)的 Android 開發(fā)中有古老的 View 動(dòng)畫和目前流行的屬性動(dòng)畫,如今 View 動(dòng)畫幾乎已被廣大開發(fā)者所拋棄,屬性動(dòng)畫因其可以作用于任何對(duì)象的靈活和強(qiáng)大特性而被開發(fā)者所擁抱。既然屬性動(dòng)畫這么強(qiáng)大,那么它是否能用在 Compose 開發(fā)中呢?如果能那跟傳統(tǒng) UI 開發(fā)中使用又有什么區(qū)別呢?本篇就帶領(lǐng)你來(lái)探索一下在 Compose 中屬性動(dòng)畫的使用。

使用探索

在傳統(tǒng) Android 開發(fā)中,屬性動(dòng)畫使用得最多的是 ObjectAnimatorValueAnimator,接下來(lái)就探索一下在 Compose 中如何使用它們來(lái)實(shí)現(xiàn)動(dòng)畫效果。

ObjectAnimator 使用探索

首先看一下在傳統(tǒng) Android 開發(fā)中如何使用屬性動(dòng)畫,比如使用屬性動(dòng)畫實(shí)現(xiàn)豎直方向向下移動(dòng)的動(dòng)畫:

val animator = ObjectAnimator.ofFloat(view, "translationY", 10f, 100f)
animator.start()

通過 ObjectAnimator作用于 View 的 translationY屬性,不斷改變 translationY 的值從而實(shí)現(xiàn)動(dòng)畫效果,一個(gè)很簡(jiǎn)單的屬性動(dòng)畫,這里就不貼運(yùn)行效果了。

那在 Compose 中能否使用 ObjectAnimator 呢?

下面使用 Compose 在界面上顯示一個(gè) 100dp*100dp 的藍(lán)色正方形方塊,代碼如下:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Box(Modifier.padding(start = 10.dp, top = 10.dp)
                .size(100.dp)
                .background(Color.Blue)
            )
        }
    }
}

運(yùn)行效果如下:

現(xiàn)在要同樣實(shí)現(xiàn)一個(gè)豎直方向移動(dòng)的動(dòng)畫效果,讓方塊從上往下移動(dòng)。在上面的屬性動(dòng)畫實(shí)現(xiàn)中 ObjectAnimator是作用于 View 組件上的,按照這個(gè)思路在這里 ObjectAnimator 就應(yīng)該作用于 Box 上,但實(shí)際上我們這里壓根拿不到 Box 的實(shí)例,因?yàn)檫@里的 Box 實(shí)際是一個(gè)函數(shù)且沒有返回值,看一下 Box 的源碼:

@Composable
fun Box(modifier: Modifier) {
    Layout({}, measurePolicy = EmptyBoxMeasurePolicy, modifier = modifier)
}

既然作用于 Box 上不行,那能不能作用于 State 上呢,Compose 是數(shù)據(jù)驅(qū)動(dòng) UI 刷新,通過數(shù)據(jù)狀態(tài)改變重組 UI 實(shí)現(xiàn)界面的刷新,把上面的 top 提取為一個(gè) State 再通過 ObjectAnimator 去改變是否可行呢?改造代碼實(shí)驗(yàn)一下:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val topPadding:MutableState<Int> = mutableStateOf(10)
        
        val animator = ObjectAnimator.ofInt(topPadding, "value", 10, 100)
        animator.duration = 1000
        
        setContent {
            Box(Modifier.padding(start = 10.dp, top = topPadding.value.dp)
                .size(100.dp)
                .background(Color.Blue)
                // 添加點(diǎn)擊事件
                .clickable {
                    // 啟動(dòng)動(dòng)畫
                    animator.start()
                }
            )
        }
    }
}

改造如下:

  • 將之前 top 的固定值提取成了一個(gè) State 變量 topPadding,當(dāng) topPadding 的值發(fā)生改變時(shí)會(huì)重組界面從而讓界面刷新
  • 聲明了 ObjectAnimator 的 animator 變量,作用于 topPadding 的 value 屬性上,并設(shè)置動(dòng)畫值從 10 到 100,動(dòng)畫時(shí)長(zhǎng) 1000ms
  • 給 Box 添加點(diǎn)擊監(jiān)聽事件啟動(dòng)動(dòng)畫

實(shí)際上寫完這段代碼,編輯器就已經(jīng)有報(bào)錯(cuò)提示了,提示如下:

說沒有找到帶 Int 參數(shù)的 setValue方法,那來(lái)看看 MutableState是否有 setValue 方法:

interface MutableState<T> : State<T> {
    override var value: T
    operator fun component1(): T
    operator fun component2(): (T) -> Unit
}

可以發(fā)現(xiàn) MutableState 中是有一個(gè) var 修飾的 value 變量的,說明是有 setValue 方法的,但是錯(cuò)誤提示是找不到帶 Int 參數(shù)的 setValue 方法,實(shí)際上 MutableState 的 setValue 的定義應(yīng)該是這樣的:

fun setValue(value:T){
    this.value = value
}

這里參數(shù)類型是泛型 T,而 ObjectAnimator 找的是明確的 Int 類型參數(shù)的方法,所以找不到。那怎么辦呢?是不是就意味著在 Compose 中無(wú)法使用 ObjectAnimator 了呢?

直接使用確實(shí)是不行,那我們能不能對(duì)其進(jìn)行封裝,不是找不到對(duì)應(yīng)的 setValue 方法嘛,那我封裝一下提供一個(gè) setValue 方法不就行了。定義一個(gè) IntState類,再提供一個(gè) mutableIntStateOf方法:

class IntState(private val state: MutableState<Int>){
    var value : Int = state.value
        get() = state.value
        set(value) {
            field = value
            state.value = value
        }
}
fun mutableIntStateOf(value: Int, policy: SnapshotMutationPolicy<Int> = structuralEqualityPolicy()) : IntState{
    val state = mutableStateOf(value, policy)
    return IntState(state)
}

IntState構(gòu)造方法傳入一個(gè) MutableState 類型的 state 參數(shù),然后提供一個(gè) value 變量,get 方法返回 state.value ,set 方法將傳入值設(shè)置給 state.value,這樣 IntState 就有了一個(gè)明確的 setValue(value:Int) 的方法。

為了便于使用,封裝一個(gè) mutableIntStateOf方法,實(shí)現(xiàn)里先采用 Compose 提供的 mutableStateOf 方法獲取一個(gè) MutableState ,然后用其構(gòu)建一個(gè) IntState 進(jìn)行返回。

再改造一下上面動(dòng)畫實(shí)現(xiàn)代碼將 mutableStateOf替換成 mutableIntStateOf

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 替換為 mutableIntStateOf
        val topPadding = mutableIntStateOf(10)
        // 創(chuàng)建 ObjectAnimator 目標(biāo)為 topPadding,作用屬性為 value,值從 10 變化到 100
        val animator = ObjectAnimator.ofInt(topPadding, "value", 10, 100)
        // 設(shè)置動(dòng)畫時(shí)長(zhǎng) 1s
        animator.duration = 1000
        
        setContent {
            Box(Modifier.padding(start = 10.dp, top = topPadding.value.dp)
                .size(100.dp)
                .background(Color.Blue)
                // 添加點(diǎn)擊事件
                .clickable {
                    // 啟動(dòng)動(dòng)畫
                    animator.start()
                }
            )
        }
    }
}

現(xiàn)在不報(bào)錯(cuò)了,運(yùn)行一下看看是否有動(dòng)畫效果:

效果符合預(yù)期,說明這種辦法是可行,也說明 ObjectAnimator 在 Compose 中也是可以使用的,只是不能像傳統(tǒng) Android 開發(fā)那樣直接作用于 View 組件上,而是需要進(jìn)行二次封裝后使用。

ValueAnimator 使用探索

ObjectAnimator 使用探索完了,那么 ValueAnimator能否使用呢?Compose 以聲明式的方式通過數(shù)據(jù)驅(qū)動(dòng)界面刷新,而ValueAnimator主要用于數(shù)據(jù)的改變,好像很契合的樣子,使用 ValueAnimator 不斷改變 State 的值理論上就可以實(shí)現(xiàn)動(dòng)畫效果。還是上面的例子,改造成使用 ValueAnimator來(lái)實(shí)現(xiàn):

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 使用 mutableStateOf 創(chuàng)建 topPadding 的 State
        var topPadding by mutableStateOf(10)
        // 創(chuàng)建 ValueAnimator 從 10 變化到 100
        val animator = ValueAnimator.ofInt(10, 100)
        // 動(dòng)畫時(shí)長(zhǎng) 1s
        animator.duration = 1000
        // 設(shè)置監(jiān)聽,當(dāng)動(dòng)畫改變時(shí)動(dòng)態(tài)修改 topPadding 的值
        animator.addUpdateListener {
            topPadding = it.animatedValue as Int
        }
        setContent {
            Box(Modifier.padding(start = 10.dp, top = topPadding.dp)
                .size(100.dp)
                .background(Color.Blue)
                .clickable {
                    animator.start()
                }
            )
        }
    }
}

是否有效果呢?運(yùn)行一下看看效果:

跟上面使用 ObjectAnimator 實(shí)現(xiàn)的效果一致,說明 ValueAnimator 在 Compose 中實(shí)現(xiàn)動(dòng)畫是可行的,只是需要手動(dòng)去監(jiān)聽 ValueAnimator 值的變化然后去動(dòng)態(tài)更新 State 的值,稍微麻煩了一點(diǎn),實(shí)際上我們也可以對(duì)其進(jìn)行封裝簡(jiǎn)化其使用。

通過上面的代碼發(fā)現(xiàn),如果要在 Compose 中使用 ValueAnimator 來(lái)實(shí)現(xiàn)動(dòng)畫,對(duì)動(dòng)畫數(shù)值的改變進(jìn)行監(jiān)聽并動(dòng)態(tài)更新 State 的值是必不可少的一步,那么我們就可以將其提取進(jìn)行封裝。

/**
 * @param state 動(dòng)畫作用的目標(biāo) State
 * @param values 動(dòng)畫的變化值,可變參數(shù)
 */
fun animatorOfInt(state:MutableState<Int>, vararg values: Int) : ValueAnimator{
    // 創(chuàng)建 ValueAnimator ,參數(shù)為傳入的 values
    val animator = ValueAnimator.ofInt(*values)
    // 添加監(jiān)聽
    animator.addUpdateListener {
        // 更新 state 的 value 值
        state.value = it.animatedValue as Int
    }
    return animator
}

然后將上面的創(chuàng)建動(dòng)畫替換成使用 animatorOfInt 創(chuàng)建:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val topPadding = mutableStateOf(10)
        // 使用封裝的 animatorOfInt 方法創(chuàng)建動(dòng)畫
        val animator = animatorOfInt(topPadding, 10, 100)
        animator.duration = 1000
        setContent {
            Box(Modifier.padding(start = 10.dp, top = topPadding.value.dp)
                .size(100.dp)
                .background(Color.Blue)
                .clickable {
                    animator.start()
                }
            )
        }
    }
}

使用是不是要簡(jiǎn)單很多,不需要手動(dòng)去處理動(dòng)畫值變化的監(jiān)聽了,有點(diǎn)使用 ObjectAnimator 的感覺,只是不需要指定目標(biāo)屬性。運(yùn)行效果跟上面一致就不貼圖了。

Compose 函數(shù)中使用屬性動(dòng)畫

前面在 Compose 中使用的動(dòng)畫都是創(chuàng)建在 Compose 函數(shù)外面的,如果我們想把這個(gè)組件封裝成一個(gè)獨(dú)立的 Compose 組件就需要將動(dòng)畫的創(chuàng)建放到 Compose 函數(shù)里面,比如將上面的效果封裝成一個(gè) AnimationBox組件:

@Composable
fun AnimationBox(){
    val topPadding = mutableStateOf(10) 
    val animator = animatorOfInt(topPadding, 10, 100)
    animator.duration = 1000
    Box(modifier = Modifier.padding(start = 10.dp, top = topPadding.value.dp)
        .size(100.dp)
        .background(Color.Blue)
        .clickable {
            animator.start()
        })
}

首先 mutableStateOf 會(huì)報(bào)錯(cuò):

意思是在組合過程中創(chuàng)建 state 需要使用 remember,原因是當(dāng) state 里的值發(fā)生變化時(shí) Compose 會(huì)進(jìn)行重組導(dǎo)致函數(shù)重新執(zhí)行,如果 mutableStateOf 不加 remember則會(huì)每次重組都重新創(chuàng)建 state,導(dǎo)致 UI 上使用的值每次都是初始值而得不到刷新。

既然報(bào)錯(cuò)那就給他加上 remember:

@Composable
fun AnimationBox(){
    val topPadding = remember { mutableStateOf(10) }
    ...
}

然后在使用的地方直接使用 AnimationBox() 即可:

setContent {
    AnimationBox()
}

運(yùn)行后發(fā)現(xiàn)效果跟之前一樣,那是不是就可以了呢?

實(shí)際上上面的代碼是還存在問題的,前面說在 Compose 重組時(shí)會(huì)重新執(zhí)行 Compose 組件的代碼,也就是在界面刷新時(shí)會(huì)多次重復(fù)創(chuàng)建動(dòng)畫對(duì)象,我們?cè)?animatorOfInt 函數(shù)里添加一個(gè)日志再看看運(yùn)行時(shí)的日志輸出:

fun  animatorOfInt(state:MutableState<Int>, vararg values: Int) : ValueAnimator{
    println("-------call animatorOfInt--------")
  ...
}

輸出結(jié)果:

I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------
I/System.out: -------call animatorOfInt--------

日志確實(shí)輸出了多次,意味著動(dòng)畫確實(shí)創(chuàng)建了多次,那怎么解決呢?

前面說了 remember可以解決重組時(shí)重復(fù)創(chuàng)建的問題,所以只需在創(chuàng)建動(dòng)畫上套上 remember即可,如下:

val animator = remember { animatorOfInt(topPadding, 10, 100) }

修改后再看日志,發(fā)現(xiàn)就只在第一次進(jìn)行了創(chuàng)建,動(dòng)畫執(zhí)行過程中并沒有再次創(chuàng)建。

為了方便使用,可以再封裝一個(gè) rememberAnimatorOfInt方法:

@Composable
fun rememberAnimatorOfInt(state:MutableState<Int>, vararg values: Int) : ValueAnimator{
   return remember { animatorOfInt(state, *values) }
}

在 animatorOfInt 上套了一個(gè) remember,這樣使用時(shí)就可以直接使用 rememberAnimatorOfInt 方法:

val animator = rememberAnimatorOfInt(topPadding, 10, 100)

remember 是 Compose 提供的在 Compose 函數(shù)中緩存狀態(tài)的方法,解決在 Compose 重組時(shí)重復(fù)創(chuàng)建的問題,關(guān)于 remember 更多使用大家可以自行查詢相關(guān)資料,本專欄主要講解動(dòng)畫的使用就不過多贅述。

實(shí)戰(zhàn)

前面介紹了屬性動(dòng)畫在 Compose 中的運(yùn)用,那在實(shí)際開發(fā)中到底好不好用呢?接下來(lái)我們通過一個(gè)實(shí)例來(lái)看看。

先看一下最終實(shí)現(xiàn)的效果:

一個(gè)上傳按鈕的動(dòng)畫效果,動(dòng)畫主要分為三階段:

  • 上傳開始
  • 按鈕從圓角矩形變成圓形
  • 按鈕顏色從藍(lán)色變成中間白色,邊框灰色
  • 文字逐漸消失
  • 上傳進(jìn)度
  • 邊框根據(jù)進(jìn)度變?yōu)樗{(lán)色
  • 上傳完成
  • 按鈕從圓形變成圓角矩形
  • 按鈕顏色變成紅色
  • 文字逐漸顯示,且文字變?yōu)?“Success”

上傳開始動(dòng)畫

先把按鈕的初始狀態(tài)使用 Compose 實(shí)現(xiàn):

@Composable
fun UploadButton() {
    Box(
        modifier = Modifier
            .padding(start = 10.dp, top = 10.dp)
            .width(180.dp),
        contentAlignment = Alignment.Center
    ) {
        Box(
            modifier = Modifier
                .clip(RoundedCornerShape(24.dp))
                .background(Color.Blue)
                .size(180.dp, 48.dp),
            contentAlignment = Alignment.Center,
        ) {
            Text("Upload", color = Color.White)
        }
    }
}

運(yùn)行效果如下:

下面就為這按鈕添加動(dòng)畫,前面講了動(dòng)畫主要作用于 State 上,所以需要先將使用到的數(shù)據(jù)提取成對(duì)應(yīng)的狀態(tài):

@Composable
fun UploadButton() {
    val originWidth = 180.dp
    val circleSize = 48.dp
    var text by remember { mutableStateOf("Upload") }
    val textAlpha = remember { mutableStateOf(1.0f) }
    val backgroundColor = remember { mutableStateOf(Color.Blue) }
    val boxWidth = remember { mutableStateOf(originWidth) }
    Box(
        modifier = Modifier
            .padding(start = 10.dp, top = 10.dp)
            .width(originWidth),
        contentAlignment = Alignment.Center
    ) {
        Box(
            modifier = Modifier
                .clip(RoundedCornerShape(height/2))
                .background(backgroundColor.value)
                .size(boxWidth.value, height),
            contentAlignment = Alignment.Center,
        ) {
            Text(text, color = Color.White, modifier = Modifier.alpha(textAlpha.value))
        }
    }
}

創(chuàng)建開始上傳的動(dòng)畫:

@Composable
fun UploadButton() {
  ...
    val uploadStartAnimator = remember {
        // 創(chuàng)建 AnimatorSet
        val animatorSet = AnimatorSet()
        // 按鈕寬度變化動(dòng)畫
        val widthAnimator = animatorOfDp(boxWidth, arrayOf(originWidth, circleSize))
        // 文字消失動(dòng)畫
        val textAnimator = animatorOfFloat(textAlpha, 1f, 0.0f)
        // 按鈕顏色動(dòng)畫
        val colorAnimator = animatorOfColor(backgroundColor, arrayOf(Color.Blue, Color.Gray))
        // 動(dòng)畫添加到 AnimatorSet
        animatorSet.playTogether(widthAnimator, textAnimator, colorAnimator)
        animatorSet
    }
    Box(...) {
        Box(
            modifier = Modifier
                ...
                .clickable {
                    // 點(diǎn)擊執(zhí)行動(dòng)畫
                    uploadStartAnimator.start()
                },
            ...
        )
    }
}

分別創(chuàng)建按鈕寬度、按鈕顏色和文字 alpha 值變化的動(dòng)畫,因需同時(shí)執(zhí)行多個(gè)動(dòng)畫,這里使用 AnimatorSet 進(jìn)行同時(shí)執(zhí)行,然后在按鈕上添加點(diǎn)擊事件進(jìn)行動(dòng)畫執(zhí)行。

上面的 animatorOfDpanimatorOfFloat、animatorOfColor都是自定義封裝的函數(shù),封裝方法與上面介紹的 animatorOfInt基本相同,源碼可通過文章最后附的源碼地址進(jìn)行查看。

運(yùn)行效果如下:

好像還差點(diǎn),中間應(yīng)該是白色的,在 Box 下再添加一個(gè)白色圓形的 Box,默認(rèn) alpha 是 0,上傳開始時(shí) alpha 從 0 變成 1 :

@Composable
fun UploadButton() {
    ...
    val progressAlpha = remember { mutableStateOf(0.0f) }
    val uploadStartAnimator = remember {
        ...
        // 中間白色透明度變化動(dòng)畫
        val centerAlphaAnimator = animatorOfFloat(progressAlpha, 0.0f, 1f)
        animatorSet.playTogether(widthAnimator, textAnimator, colorAnimator, centerAlphaAnimator)
        animatorSet
    }
    Box(...) {
        Box(...) {
            // 白色圓形
            Box(
                modifier = Modifier.size(40.dp).clip(RoundedCornerShape(20.dp))
                    .alpha(progressAlpha.value).background(Color.White)
            )
            Text(text, color = Color.White, modifier = Modifier.alpha(textAlpha.value))
        }
    }
}

運(yùn)行效果如下:

上傳進(jìn)度動(dòng)畫

這里通過自定義 clip 的一個(gè)弧形的 shape 來(lái)實(shí)現(xiàn)進(jìn)度,自定義代碼如下:

class ArcShape(private val progress: Int) : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val path = Path().apply {
            moveTo(size.width / 2f, size.height / 2f)
            arcTo(Rect(0f, 0f, size.width, size.height), -90f, progress / 100f * 360f, false)
            close()
        }
        return Outline.Generic(path)
    }
}

傳入一個(gè)進(jìn)度值(0-100),然后根據(jù)進(jìn)度值算出一個(gè)繪制的弧度,使用這個(gè)自定義的 ArcShape 代碼如下:

 Box(Modifier.size(48.dp).clip(ArcShape(30)).background(Color.Blue))

效果:

所以只需動(dòng)態(tài)改變 ArcShape 的 progress 參數(shù)的值就能實(shí)現(xiàn)上傳進(jìn)度效果,修改代碼如下:

@Composable
fun PreviewUploadButton() {
    ...
    val progress = remember { mutableStateOf(0) }
    //上傳進(jìn)度動(dòng)畫
    val progressAnimator = remember {
        val animator = animatorOfInt(progress, 0, 100)
        animator.duration = 1000
        animator
    }
    val uploadStartAnimator = remember {
        ...
        // 添加動(dòng)畫監(jiān)聽,完成后執(zhí)行進(jìn)度動(dòng)畫
        animatorSet.addListener(onEnd = {
            progressAnimator.start()
        })
        animatorSet
    }
    Box(...) {
        Box(...) {
            // 進(jìn)度 Box
            Box(
                modifier = Modifier.size(height).clip(ArcShape(progress.value))
                    .alpha(progressAlpha.value).background(Color.Blue)
            )
            ...
        }
    }
}

運(yùn)行效果:

上傳完成動(dòng)畫

最后是上傳完成動(dòng)畫就很簡(jiǎn)單了,基本就是開始動(dòng)畫的反向,只是按鈕顏色從藍(lán)色變成了紅色,動(dòng)畫在上傳進(jìn)度動(dòng)畫完成時(shí)執(zhí)行:

@Composable
fun PreviewUploadButton() {
    ...
    
    val endAnimatorSet = remember {
        val animatorSet = AnimatorSet()
        val widthAnimator = animatorOfDp(boxWidth, arrayOf(circleSize, originWidth))
        val centerAnimator = animatorOfFloat(progressAlpha, 1f, 0f)
        val textAnimator = animatorOfFloat(textAlpha, 0f, 1f)
        val colorAnimator = animatorOfColor(backgroundColor, arrayOf(Color.Blue, Color.Red))
        animatorSet.playTogether(widthAnimator, centerAnimator, textAnimator, colorAnimator)
        animatorSet.addListener(onStart = {
            text = "Success"
        })
        animatorSet
    }
    val progressAnimator = remember {
        val animator = animatorOfInt(progress, 0, 100)
        animator.duration = 1000
        animator.addListener(onEnd = {
            endAnimatorSet.start()
        })
        animator
    }
    ...
}

最終效果:

最后

通過本篇文章的探索可以發(fā)現(xiàn)屬性動(dòng)畫在 Compose 中確實(shí)是可以使用的,雖然跟傳統(tǒng) UI 開發(fā)中使用屬性動(dòng)畫有所區(qū)別,但確實(shí)能用,而且通過一個(gè)簡(jiǎn)單的實(shí)戰(zhàn)示例發(fā)現(xiàn)好像還挺好用的。好了,我已經(jīng)學(xué)會(huì) Compose 的動(dòng)畫開發(fā)了,什么?Compose 還單獨(dú)提供了一套動(dòng)畫 API ?

屬性動(dòng)畫這不是挺好使的么,這不是多此一舉么,難道 Compose 的動(dòng)畫 API 比屬性動(dòng)畫還好用、還強(qiáng)大?如果感興趣請(qǐng)關(guān)注本專欄,從下一篇開始帶你真正走進(jìn) Compose 的動(dòng)畫世界。

源碼地址:ComposeAnimationDemo

以上就是Android Compose 屬性動(dòng)畫使用探索詳解的詳細(xì)內(nèi)容,更多關(guān)于Android Compose 屬性動(dòng)畫的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論