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

Compose?動(dòng)畫(huà)藝術(shù)探索之可見(jiàn)性動(dòng)畫(huà)示例詳解

 更新時(shí)間:2022年09月22日 14:37:25   作者:Zhujiang  
這篇文章主要為大家介紹了Compose?動(dòng)畫(huà)藝術(shù)探索之可見(jiàn)性動(dòng)畫(huà)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

本篇文章是此專欄的第二篇文章,上一篇文章簡(jiǎn)單寫了下 Compose 的動(dòng)畫(huà),讓大家先看了下 Compose 開(kāi)箱即用的動(dòng)畫(huà)效果,效果還是挺好的,感興趣的可以去看下:Compose 動(dòng)畫(huà)藝術(shù)探索之瞅下 Compose 的動(dòng)畫(huà)

從可見(jiàn)性動(dòng)畫(huà)看起

可見(jiàn)性動(dòng)畫(huà)在上一篇文章中介紹過(guò),不過(guò)只是簡(jiǎn)單使用,沒(méi)看過(guò)上一篇文章的也不用擔(dān)心,給大家看下可見(jiàn)性動(dòng)畫(huà)的實(shí)際效果。

實(shí)現(xiàn)代碼也很簡(jiǎn)單,來(lái)回顧下:

val visible = remember { mutableStateOf(true) }
AnimatedVisibility(visible = visible.value,) {
    Text(text = "天青色等煙雨,而我在等你,炊煙裊裊升起,隔江千萬(wàn)里")
}

上一篇文章主要介紹了 Compose 動(dòng)畫(huà)的便攜之處,例如上面代碼,確實(shí)非常簡(jiǎn)單就能實(shí)現(xiàn)之前原生安卓中比較難實(shí)現(xiàn)的動(dòng)畫(huà)效果,今天咱們就來(lái)稍微深入一點(diǎn)看看,從小節(jié)標(biāo)題也能知道,就從可見(jiàn)性動(dòng)畫(huà)來(lái)看!

怎么看呢?直接點(diǎn)進(jìn)去源碼來(lái)看!先來(lái)看看 AnimatedVisibility 的函數(shù)定義吧!

@Composable
fun AnimatedVisibility(
    visible: Boolean,
    modifier: Modifier = Modifier,
    enter: EnterTransition = fadeIn() + expandIn(),
    exit: ExitTransition = shrinkOut() + fadeOut(),
    label: String = "AnimatedVisibility",
    content: @Composable() AnimatedVisibilityScope.() -> Unit
) {
    val transition = updateTransition(visible, label)
    AnimatedEnterExitImpl(transition, { it }, modifier, enter, exit, content)
}

其實(shí)可組合項(xiàng) AnimatedVisibility 不是只有這一個(gè),目前 Compose 1.3.0-beta02 版本中有六個(gè),這個(gè)咱們待會(huì)再說(shuō),先看這一個(gè),也是第一個(gè),可以看到函數(shù)中一共可以接收六個(gè)參數(shù),下面先來(lái)看看這六個(gè)參數(shù)分別有什么作用吧:

  • visible:定義內(nèi)容是否應(yīng)該可見(jiàn),true 為可見(jiàn),false 為不可見(jiàn)
  • modifier:修飾符,這個(gè)就不多說(shuō)了,在 ComposeModifier 簡(jiǎn)直隨處可見(jiàn)
  • enter:內(nèi)容出現(xiàn)時(shí)的動(dòng)畫(huà),可以看到這個(gè)參數(shù)有默認(rèn)值,默認(rèn)值為 fadeIn() + expandIn() ,大致意思為淡入并擴(kuò)展開(kāi)
  • exit:內(nèi)容由可見(jiàn)變?yōu)椴豢梢?jiàn)時(shí)的動(dòng)畫(huà),同樣的,這個(gè)參數(shù)也有默認(rèn)值,默認(rèn)值為 shrinkOut() + fadeOut() ,大致意思為縮小并淡出消失
  • label:字面意思理解為標(biāo)簽,默認(rèn)值為 AnimatedVisibility ,可以自定義做標(biāo)記,用于區(qū)分不同動(dòng)畫(huà)
  • content:需要添加可見(jiàn)性動(dòng)畫(huà)的可組合項(xiàng)。

上面這些參數(shù)除了 enterexit 外都比較好理解,這里就不做過(guò)多解釋,重點(diǎn)來(lái)看下 enterexit ,可以看到 enter 的類型為 EnterTransition ,exit 的類型為 ExitTransition ,那么接下來(lái)咱們來(lái)分別看看 EnterTransitionExitTransition 吧!

這里其實(shí)有一個(gè)小問(wèn)題,可以看到上面 Gif 圖中并不是淡入并擴(kuò)展和縮小并消失,這是為什么呢?繼續(xù)往下看就能找到答案!

進(jìn)入過(guò)渡——EnterTransition

顧名思義,這個(gè)類主要是為了做進(jìn)入過(guò)渡的,來(lái)簡(jiǎn)單看下它的源碼吧:

@Immutable
sealed class EnterTransition {
    internal abstract val data: TransitionData
    // 組合不同的進(jìn)入轉(zhuǎn)換。組合的順序并不重要,因?yàn)檫@些將同時(shí)啟動(dòng)
    @Stable
    operator fun plus(enter: EnterTransition): EnterTransition {
        return EnterTransitionImpl(
            TransitionData(
                fade = data.fade ?: enter.data.fade,
                slide = data.slide ?: enter.data.slide,
                changeSize = data.changeSize ?: enter.data.changeSize,
                scale = data.scale ?: enter.data.scale
            )
        )
    }
    companion object {
        // 當(dāng)不需要輸入轉(zhuǎn)換時(shí),可以使用此函數(shù)。
        val None: EnterTransition = EnterTransitionImpl(TransitionData())
    }
}

可以看到 EnterTransition 是一個(gè)密封類, 類中有一個(gè)抽象的不可變值 data ,類型為 TransitionData ,這個(gè)放到下面來(lái)說(shuō);類中還有一個(gè)函數(shù),而且該函數(shù)有 operator 前綴, 這表示運(yùn)算符重載,重載了“+”號(hào),所以就可以使用“+”來(lái)組合不同的輸入動(dòng)畫(huà)了,函數(shù)接收的參數(shù)也是 EnterTransition ,然后直接返回 EnterTransitionImpl ,又沒(méi)見(jiàn)過(guò),怎么辦?繼續(xù)看看 EnterTransitionImpl 是個(gè)啥!

@Immutable
private class EnterTransitionImpl(override val data: TransitionData) : EnterTransition()

可以看到 EnterTransitionImpl 類很簡(jiǎn)單,是一個(gè)私有類,繼承自 EnterTransition ,注意類上有 Immutable 注解, Immutable 注解可用于將類標(biāo)記為生成不可變實(shí)例,但類的不變性沒(méi)有得到驗(yàn)證,它是類型的一種承諾,即在構(gòu)造實(shí)例之后,所有公開(kāi)可訪問(wèn)的屬性和字段都不會(huì)更改。 EnterTransitionImpl 還需要實(shí)現(xiàn)父類的抽象值,所有有 TransitionData 類型的參數(shù) data ,上面咱們簡(jiǎn)單提到了 TransitionData ,這里來(lái)看下吧!

@Immutable
internal data class TransitionData(
    val fade: Fade? = null,
    val slide: Slide? = null,
    val changeSize: ChangeSize? = null,
    val scale: Scale? = null
)

可以看到 TransitionData 類也有 Immutable 注解,這里就不做過(guò)多介紹,這是一個(gè)包內(nèi)可見(jiàn)的數(shù)據(jù)類,里面有四個(gè)不可變值,分別是 Fade 、SlideChangeSize 、Scale ,其實(shí)從名稱就能看出這幾個(gè)參數(shù)分別代表的意思,不過(guò)還是來(lái)看下它們的源碼吧!

@Immutable
internal data class Fade(val alpha: Float, val animationSpec: FiniteAnimationSpec<Float>)
@Immutable
internal data class Slide(
    val slideOffset: (fullSize: IntSize) -> IntOffset,
    val animationSpec: FiniteAnimationSpec<IntOffset>
)
@Immutable
internal data class ChangeSize(
    val alignment: Alignment,
    val size: (fullSize: IntSize) -> IntSize = { IntSize(0, 0) },
    val animationSpec: FiniteAnimationSpec<IntSize>,
    val clip: Boolean = true
)
@Immutable
internal data class Scale(
    val scale: Float,
    val transformOrigin: TransformOrigin,
    val animationSpec: FiniteAnimationSpec<Float>
)

可以看到這四個(gè)類都是不可變的數(shù)據(jù)類,分別表示顏色轉(zhuǎn)變、滑動(dòng)、大小變化及縮放。這幾個(gè)類有一個(gè)共同點(diǎn),都有一個(gè)共同的參數(shù) animationSpec ,參數(shù)類型為 FiniteAnimationSpec ,來(lái)看看 FiniteAnimationSpec 是個(gè)啥?

interface FiniteAnimationSpec<T> : AnimationSpec<T> {
    override fun <V : AnimationVector> vectorize(
        converter: TwoWayConverter<T, V>
    ): VectorizedFiniteAnimationSpec<V>
}

可以看到 FiniteAnimationSpec 是一個(gè)接口,繼承自 AnimationSpec ,簡(jiǎn)單理解就是有限動(dòng)畫(huà)規(guī)格,定義了動(dòng)畫(huà)的時(shí)長(zhǎng)及動(dòng)畫(huà)效果等,類似于原生安卓中的什么呢?嗯。。。差值器吧!FiniteAnimationSpec 是所有非無(wú)限動(dòng)畫(huà)實(shí)現(xiàn)的接口,包括: TweenSpec, SpringSpecKeyframesSpec, RepeatableSpecSnapSpec 等等,上一篇文章中說(shuō)到的無(wú)限循環(huán)動(dòng)畫(huà) InfiniteRepeatableSpec 沒(méi)有繼承這個(gè)接口,其實(shí)從名字看就知道了,InfiniteRepeatableSpec 也繼承自 AnimationSpec 。。。。

不行不行,扯太遠(yuǎn)了,其實(shí)看源碼就是這樣,看著看著一直往下看就會(huì)迷失了最初的目標(biāo),越看越多,越看越多,這里就先不接著往下看了,再看就沒(méi)完沒(méi)了了,這里咱們知道這四個(gè)類大概存儲(chǔ)了什么數(shù)據(jù)就行了。動(dòng)畫(huà)規(guī)格咱們放到之后的文章中慢慢看,今天主要來(lái)過(guò)一遍可見(jiàn)性動(dòng)畫(huà)!

簡(jiǎn)單總結(jié)下, EnterTransition 類中有一個(gè)函數(shù),進(jìn)行了運(yùn)算符重載,可以有多個(gè)動(dòng)畫(huà)同時(shí)進(jìn)行。

關(guān)閉過(guò)渡——ExitTransition

其實(shí)看完剛才的 EnterTransition 類再來(lái)看 ExitTransition 就會(huì)覺(jué)得很簡(jiǎn)單了,不信的話咱們來(lái)看下 ExitTransition 的源碼:

@Immutable
sealed class ExitTransition {
    internal abstract val data: TransitionData
    // 結(jié)合不同的退出轉(zhuǎn)換,組合順序并不重要
    @Stable
    operator fun plus(exit: ExitTransition): ExitTransition {
        return ExitTransitionImpl(
            TransitionData(
                fade = data.fade ?: exit.data.fade,
                slide = data.slide ?: exit.data.slide,
                changeSize = data.changeSize ?: exit.data.changeSize,
                scale = data.scale ?: exit.data.scale
            )
        )
    }
    companion object {
        // 當(dāng)不需要內(nèi)置動(dòng)畫(huà)時(shí)使用
        val None: ExitTransition = ExitTransitionImpl(TransitionData())
    }
}

是不是基本一致,連抽象不可變值都一摸一樣,甚至值的名稱都沒(méi)變!唯一不同的是 EnterTransition 的實(shí)現(xiàn)類為 EnterTransitionImpl ,而 ExitTransition 的子類為 ExitTransitionImpl ,那就再看看 ExitTransitionImpl !

@Immutable
private class ExitTransitionImpl(override val data: TransitionData) : ExitTransition()

EnterTransitionImpl 不能說(shuō)相似,只能說(shuō)一摸一樣。。。所以就不做過(guò)多介紹。。。

過(guò)渡——Transition

文章開(kāi)頭的時(shí)候看 AnimatedVisibility 函數(shù)中只有下面的兩行代碼,

val transition = updateTransition(visible, label)
AnimatedEnterExitImpl(transition, { it }, modifier, enter, exit, content)

這一小節(jié)咱們先來(lái)看第一行,可以看到調(diào)用了 updateTransition 函數(shù), 傳入了當(dāng)前顯示狀態(tài)和標(biāo)簽,來(lái)具體看下這個(gè)函數(shù)吧!

@Composable
fun <T> updateTransition(
    targetState: T,
    label: String? = null
): Transition<T> {
    val transition = remember { Transition(targetState, label = label) }
    transition.animateTo(targetState)
    DisposableEffect(transition) {
        onDispose {
            // 出去的時(shí)候清理干凈,確保觀察者不會(huì)被困在中間狀態(tài)
            transition.onTransitionEnd()
        }
    }
    return transition
}

可以看到這個(gè)函數(shù)也是一個(gè)可組合項(xiàng),返回值為 Transition ,函數(shù)中先記住并構(gòu)建了一個(gè) Transition ,然后調(diào)用了 TransitionanimateTo 函數(shù)來(lái)執(zhí)行過(guò)渡動(dòng)畫(huà),然后調(diào)用了需要清理的效應(yīng) DisposableEffect ,之后在 onDispose 中調(diào)用了 onTransitionEnd 函數(shù),以防卡在這里,最后返回剛才構(gòu)建的 Transition

函數(shù)中的內(nèi)容不難理解,現(xiàn)在唯一困惑的是 Transition 是個(gè)什么東西!那就來(lái)看看!

@Stable
class Transition<S> @PublishedApi internal constructor(
    private val transitionState: MutableTransitionState<S>,
    val label: String? = null
)

這就是 Transition 的類聲明,Transition 在狀態(tài)級(jí)別上管理所有子動(dòng)畫(huà)。子動(dòng)畫(huà)可以使用Transition 以聲明的方式創(chuàng)建。animateFloatanimateValue、animateColor animateColor等。當(dāng) targetState 改變時(shí),Transition 將自動(dòng)啟動(dòng)或調(diào)整其所有子動(dòng)畫(huà)的路線,使其動(dòng)畫(huà)到為每個(gè)動(dòng)畫(huà)定義的新目標(biāo)值。

可以看到 Transition 構(gòu)造函數(shù)中接收一個(gè) MutableTransitionState 類型的參數(shù)和一個(gè) lable ,但咱們看到上面?zhèn)魅氲牟⒉皇?MutableTransitionState 類型的參數(shù),肯定還有別的構(gòu)造函數(shù)!

internal constructor(
    initialState: S,
    label: String?
) : this(MutableTransitionState(initialState), label)

沒(méi)錯(cuò),確實(shí)還有一個(gè)構(gòu)造函數(shù),接下來(lái)看下 MutableTransitionState 吧!

class MutableTransitionState<S>(initialState: S) {
    // 當(dāng)前的狀態(tài)
    var currentState: S by mutableStateOf(initialState)
        internal set
    // 過(guò)渡的目標(biāo)狀態(tài)
    var targetState: S by mutableStateOf(initialState)
    // 是否空閑
    val isIdle: Boolean
        get() = (currentState == targetState) && !isRunning
    // 是否運(yùn)行
    internal var isRunning: Boolean by mutableStateOf(false)
}

可以看到 MutableTransitionState 中構(gòu)建了幾個(gè)需要的狀態(tài),具體表示什么在上面代碼中添加了注釋。

過(guò)渡動(dòng)畫(huà)實(shí)現(xiàn)——AnimatedEnterExitImpl

剛才看了 AnimatedVisibility 函數(shù)中的第一行代碼,下面咱們來(lái)看下第二行代碼:

AnimatedEnterExitImpl(transition, { it }, modifier, enter, exit, content)

這塊調(diào)用了一個(gè)實(shí)現(xiàn)函數(shù),將剛構(gòu)建好的 Transition 和之前的 EnterTransitionExitTransition 統(tǒng)統(tǒng)傳了進(jìn)去,下面就來(lái)看下 AnimatedEnterExitImpl !

@Composable
private fun <T> AnimatedEnterExitImpl(
    transition: Transition<T>,visible: (T) -> Boolean,
    modifier: Modifier,enter: EnterTransition,
    exit: ExitTransition,content: @Composable() AnimatedVisibilityScope.() -> Unit
) {
    val isAnimationVisible = remember(transition) {
        mutableStateOf(visible(transition.currentState))
    }
    if (visible(transition.targetState) || isAnimationVisible.value || transition.isSeeking) {
        val childTransition = transition.createChildTransition(label = "EnterExitTransition") {
            transition.targetEnterExit(visible, it)
        }
        LaunchedEffect(childTransition) {
            snapshotFlow {
                childTransition.currentState == EnterExitState.Visible ||
                    childTransition.targetState == EnterExitState.Visible
            }.collect {
                isAnimationVisible.value = it
            }
        }
        AnimatedEnterExitImpl(childTransition,modifier,
            enter = enter,exit = exit,content = content
        )
    }
}

這塊代碼有點(diǎn)多啊,但不要害怕,可以看到基本上這里使用到的類在剛才咱們都看過(guò)了,接下來(lái)需要的就是一行一行往下看,看看哪個(gè)沒(méi)見(jiàn)過(guò)咱們?cè)倏矗?/p>

函數(shù)中先記錄了當(dāng)前的狀態(tài),然后判斷當(dāng)前的狀態(tài)值是否為 true,如果為 true 的話則創(chuàng)建子過(guò)渡,老規(guī)矩,來(lái)看看 createChildTransition

@Composable
inline fun <S, T> Transition<S>.createChildTransition(
    label: String = "ChildTransition",
    transformToChildState: @Composable (parentState: S) -> T,
): Transition<T> {
    val initialParentState = remember(this) { this.currentState }
    val initialState = transformToChildState(if (isSeeking) currentState else initialParentState)
    val targetState = transformToChildState(this.targetState)
    return createChildTransitionInternal(initialState, targetState, label)
}

可以看到 createChildTransitionTransition 的一個(gè)擴(kuò)展函數(shù),還是一個(gè)高階函數(shù),函數(shù)內(nèi)獲取了高階函數(shù)中的返回值,然后直接返回調(diào)用了 createChildTransitionInternal ,并傳入獲取的值,這個(gè)值目前還不知道是什么,只知道是 targetEnterExit 返回的數(shù)據(jù),這個(gè)一會(huì)再看,先接著看 createChildTransitionInternal 函數(shù):

@Composable
internal fun <S, T> Transition<S>.createChildTransitionInternal(
    initialState: T,
    targetState: T,
    childLabel: String,
): Transition<T> {
    val transition = remember(this) {
        Transition(MutableTransitionState(initialState), "${this.label} > $childLabel")
    }
    DisposableEffect(transition) {
        addTransition(transition)
        onDispose {
            removeTransition(transition)
        }
    }
    if (isSeeking) {
        transition.setPlaytimeAfterInitialAndTargetStateEstablished(
            initialState,
            targetState,
            this.lastSeekedTimeNanos
        )
    } else {
        transition.updateTarget(targetState)
        transition.isSeeking = false
    }
    return transition
}

可以看到 createChildTransitionInternal 也是 Transition 的一個(gè)擴(kuò)展函數(shù),然后函數(shù)中也使用了需要清理的效應(yīng),之后判斷 isSeeking 的值是,isSeeking 的值在 setPlaytimeAfterInitialAndTargetStateEstablished 函數(shù)中會(huì)被置為 true,如果 isSeeking 值為 true 則調(diào)用 setPlaytimeAfterInitialAndTargetStateEstablished 函數(shù),用來(lái)設(shè)置初始狀態(tài)和目標(biāo)狀態(tài)建立后的時(shí)間,如果為 false,則更新?tīng)顟B(tài)值。

到這里 createChildTransition 函數(shù)咱們大概看了下,但剛才還有一個(gè)扣,剛才說(shuō)了不知道目標(biāo)值是什么,因?yàn)槟鞘?targetEnterExit 的返回值,現(xiàn)在咱們來(lái)看看!

@Composable
private fun <T> Transition<T>.targetEnterExit(
    visible: (T) -> Boolean,
    targetState: T
): EnterExitState = key(this) {
    if (this.isSeeking) {
        if (visible(targetState)) {
            Visible
        } else {
            if (visible(this.currentState)) {
                PostExit
            } else {
                PreEnter
            }
        }
    } else {
        val hasBeenVisible = remember { mutableStateOf(false) }
        if (visible(currentState)) {
            hasBeenVisible.value = true
        }
        if (visible(targetState)) {
            EnterExitState.Visible
        } else {
            // If never been visible, visible = false means PreEnter, otherwise PostExit
            if (hasBeenVisible.value) {
                EnterExitState.PostExit
            } else {
                EnterExitState.PreEnter
            }
        }
    }
}

同樣的,targetEnterExit 也是一個(gè)擴(kuò)展函數(shù),返回值為 EnterExitState 。這里也使用了 isSeeking 來(lái)進(jìn)行判斷,然后根據(jù)當(dāng)前的值來(lái)設(shè)置不同的 EnterExitState 。EnterExitState 又是個(gè)啥呢???接著來(lái)看!

enum class EnterExitState {
    // 自定義進(jìn)入動(dòng)畫(huà)的初始狀態(tài)。
    PreEnter,
    // 自定義進(jìn)入動(dòng)畫(huà)的目標(biāo)狀態(tài),也是動(dòng)畫(huà)過(guò)程中自定義退出動(dòng)畫(huà)的初始狀態(tài)。
    Visible,
    // 自定義退出動(dòng)畫(huà)的目標(biāo)狀態(tài)。
    PostExit
}

奧,EnterExitState 只是一個(gè)枚舉類,定義了三種狀態(tài):初始狀態(tài)、進(jìn)入動(dòng)畫(huà)的狀態(tài)和退出動(dòng)畫(huà)的狀態(tài)。

下面接著來(lái)看 AnimatedEnterExitImpl

LaunchedEffect(childTransition) {
            snapshotFlow {
                childTransition.currentState == EnterExitState.Visible ||
                    childTransition.targetState == EnterExitState.Visible
            }.collect {
                isAnimationVisible.value = it
            }
        }
AnimatedEnterExitImpl(childTransition,modifier,
            enter = enter,exit = exit,content = content
        )

這里使用了 LaunchedEffect 效應(yīng),并使用 snapshotFlowState 轉(zhuǎn)為了 Flow ,然后將值設(shè)置到 isAnimationVisible 。

后面又調(diào)用了相同名字的一個(gè)函數(shù) AnimatedEnterExitImpl

@Composable
private inline fun AnimatedEnterExitImpl(
    transition: Transition<EnterExitState>,
    modifier: Modifier,
    enter: EnterTransition,
    exit: ExitTransition,
    content: @Composable AnimatedVisibilityScope.() -> Unit
) {
    if (transition.currentState == EnterExitState.Visible ||
        transition.targetState == EnterExitState.Visible
    ) {
        val scope = remember(transition) { AnimatedVisibilityScopeImpl(transition) }
        Layout(
            content = { scope.content() },
            modifier = modifier.then(transition.createModifier(enter, exit, "Built-in")),
            measurePolicy = remember { AnimatedEnterExitMeasurePolicy(scope) }
        )
    }
}

函數(shù)名字一樣,但參數(shù)不同,這里將剛才構(gòu)建好的 Transition<EnterExitState> 傳了進(jìn)來(lái),然后函數(shù)內(nèi)先對(duì)狀態(tài)進(jìn)行了過(guò)濾,然后構(gòu)建了 Layout 。

Layout 中設(shè)置了 modifier ,modifier 調(diào)用了 then 函數(shù),then 函數(shù)用于將此修飾符與另一個(gè)修飾符連接,然后連接了 transition.createModifier(enter, exit, "Built-in") ,大家發(fā)現(xiàn)點(diǎn)什么沒(méi)有,這里使用到了上面咱們構(gòu)建好了所有東西。。。那么。。。。哈哈哈哈!

柳暗花明

下面咱們就來(lái)看看 transition.createModifier 這個(gè)函數(shù),先來(lái)看下函數(shù)體:

@Composable
internal fun Transition<EnterExitState>.createModifier(
    enter: EnterTransition,
    exit: ExitTransition,
    label: String
): Modifier

嗯,沒(méi)錯(cuò),是 Transition<EnterExitState> 的一個(gè)擴(kuò)展函數(shù),也是一個(gè)可組合項(xiàng)!接著往下看幾行代碼:

var modifier: Modifier = Modifier
modifier = modifier.slideInOut(
    this,
    rememberUpdatedState(enter.data.slide),
    rememberUpdatedState(exit.data.slide),
    label
).shrinkExpand(
    this,
    rememberUpdatedState(enter.data.changeSize),
    rememberUpdatedState(exit.data.changeSize),
    label
)

構(gòu)建了一個(gè) Modifier ,然后調(diào)用了 slideInOutshrinkExpand ,沒(méi)錯(cuò),這是滑動(dòng)和縮小放大!接著來(lái)!

var shouldAnimateAlpha by remember(this) { mutableStateOf(false) }
var shouldAnimateScale by remember(this) { mutableStateOf(false) }
if (currentState == targetState && !isSeeking) {
    shouldAnimateAlpha = false
    shouldAnimateScale = false
} else {
    if (enter.data.fade != null || exit.data.fade != null) {
        shouldAnimateAlpha = true
    }
    if (enter.data.scale != null || exit.data.scale != null) {
        shouldAnimateScale = true
    }
}

創(chuàng)建兩個(gè)值來(lái)記錄是否需要透明度的轉(zhuǎn)換和縮放!下面來(lái)看下執(zhí)行的代碼:

if (shouldAnimateScale) {
    ......
    modifier = modifier.graphicsLayer {
        this.alpha = alpha
        this.scaleX = scale
        this.scaleY = scale
        this.transformOrigin = transformOrigin
    }
} else if (shouldAnimateAlpha) {
    modifier = modifier.graphicsLayer {
        this.alpha = alpha
    }
}

嗯呢,是不是豁然開(kāi)朗!但是 slideInOutshrinkExpand 函數(shù)也是可見(jiàn)性動(dòng)畫(huà)這里定義的 Modifier 的擴(kuò)展函數(shù),里面還有一些自定義的東西,但這不是本文的重點(diǎn)了。

別的可見(jiàn)性動(dòng)畫(huà)

文章開(kāi)頭說(shuō)了,可見(jiàn)性動(dòng)畫(huà)目前一共有六個(gè),聽(tīng)著很嚇人,其實(shí)大同小異,來(lái)簡(jiǎn)單看下不同吧!

@Composable
fun RowScope.AnimatedVisibility(
    visible: Boolean,
    modifier: Modifier = Modifier,
    enter: EnterTransition = fadeIn() + expandHorizontally(),
    exit: ExitTransition = fadeOut() + shrinkHorizontally(),
    label: String = "AnimatedVisibility",
    content: @Composable() AnimatedVisibilityScope.() -> Unit
) {
    val transition = updateTransition(visible, label)
    AnimatedEnterExitImpl(transition, { it }, modifier, enter, exit, content)
}
@Composable
fun ColumnScope.AnimatedVisibility(
    visible: Boolean,
    modifier: Modifier = Modifier,
    enter: EnterTransition = fadeIn() + expandVertically(),
    exit: ExitTransition = fadeOut() + shrinkVertically(),
    label: String = "AnimatedVisibility",
    content: @Composable AnimatedVisibilityScope.() -> Unit
) {
    val transition = updateTransition(visible, label)
    AnimatedEnterExitImpl(transition, { it }, modifier, enter, exit, content)
}

上面這兩個(gè)和咱們上面說(shuō)的基本一樣,只不過(guò)一個(gè)是 RowScope 的擴(kuò)展函數(shù),另一個(gè)是 ColumnScope 的擴(kuò)展函數(shù),并且在默認(rèn)動(dòng)畫(huà)上還有些區(qū)別,RowScope 默認(rèn)是橫向的擴(kuò)展和收縮,ColumnScope 是縱向的擴(kuò)展和收縮,更加方便咱們?nèi)粘U{(diào)用!這也就解釋了文章開(kāi)頭提出的小問(wèn)題!

接著再來(lái)看別的!

@Composable
fun AnimatedVisibility(
    visibleState: MutableTransitionState<Boolean>,
    modifier: Modifier = Modifier,
    enter: EnterTransition = fadeIn() + expandIn(),
    exit: ExitTransition = fadeOut() + shrinkOut(),
    label: String = "AnimatedVisibility",
    content: @Composable() AnimatedVisibilityScope.() -> Unit
) {
    val transition = updateTransition(visibleState, label)
    AnimatedEnterExitImpl(transition, { it }, modifier, enter, exit, content)
}

這個(gè)和之前的就有點(diǎn)區(qū)別了,第一個(gè)參數(shù)就不同了,參數(shù)類型為 MutableTransitionState ,其實(shí)是一樣的,咱們上面也都說(shuō)到了,MutableTransitionState 的使用方法在上一篇文章中也介紹過(guò),感興趣的可以去看一下。

剩下的兩個(gè)還是 RowScopeColumnScope 的擴(kuò)展函數(shù),也是參數(shù)類型改為了 MutableTransitionState ,這里也就不做過(guò)多介紹。

結(jié)尾

本篇文章帶大家看了可見(jiàn)性動(dòng)畫(huà)的一些源碼,很多其實(shí)都是點(diǎn)到為止,并沒(méi)有一致不斷深入,一直深入就會(huì)陷入其中,忘了看源碼的本意,本文所有源碼基于 Compose 1.3.0-beta02 。

本文至此結(jié)束,有用的地方大家可以參考,當(dāng)然如果能幫助到大家,更多關(guān)于Compose 可見(jiàn)性動(dòng)畫(huà)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論