最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android中分析Jetpack?Compose動(dòng)畫內(nèi)部的實(shí)現(xiàn)原理

 更新時(shí)間:2022年09月01日 08:48:09   作者:李小白lt???????  
這篇文章主要介紹了Android中分析Jetpack?Compose動(dòng)畫內(nèi)部的實(shí)現(xiàn)原理,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,感興趣的小伙伴可以參考一下

前言

Compose的動(dòng)畫Api用起來(lái)很簡(jiǎn)單,效果看起來(lái)很神奇,那么它內(nèi)部到底是如何運(yùn)轉(zhuǎn)的呢?

使用動(dòng)畫的代碼示例:

var isOffset by remember { mutableStateOf(false) }
val offsetAnimation by animateDpAsState(targetValue = if (isOffset) 100.dp else 0.dp)
Button(
    onClick = { isOffset = !isOffset },
    modifier = Modifier.offset(0.dp, offsetAnimation)
) {
    Text(text = "點(diǎn)我進(jìn)行位移")
}

看到有一個(gè)Boolean類型的isOffset狀態(tài),控制著offsetAnimation動(dòng)畫,然后動(dòng)畫又控制著Button的offset,最終實(shí)現(xiàn)了動(dòng)畫效果

正文

我們主要就看一下animateDpAsState(animate*AsState)做了什么

跟一下animateDpAsState最后會(huì)走進(jìn)animateValueAsState方法中:

方法內(nèi)部創(chuàng)建了一個(gè)Animatable動(dòng)畫類

然后我們跟著上圖的箭頭看,在targetValue發(fā)生變化后,會(huì)通過(guò)channel來(lái)發(fā)送targetValue值的變化,然后launch啟動(dòng)一個(gè)協(xié)程,并在其中調(diào)用了animatable的animateTo方法

接著我們就看看Animatable類是如何做動(dòng)畫的:

主要就是內(nèi)部持有一個(gè)AnimationState類型(State)的internalState 變量,然后我們接著上面的代碼跟一下animateTo方法:

沒什么好說(shuō)的,包了一下targetValue,接著就調(diào)用了runAnimation方法,接著往下跟(截不下分成兩張圖):

主要邏輯就是endState.animate()
endState就是copy的Animatable中的AnimationState對(duì)象internalState,也就是動(dòng)畫的初始值

然后animation就是在animateTo方法中包裝了動(dòng)畫目標(biāo)值的對(duì)象

接著跟animate方法:

這個(gè)方法主要分為兩部分,第一部分就是構(gòu)建了一個(gè)AnimationScope,一個(gè)數(shù)據(jù)結(jié)構(gòu),用來(lái)存放動(dòng)畫需要的一些信息

第二個(gè)部分就是真正動(dòng)畫計(jì)算和生效的地方,doAnimationFrame

首先會(huì)在第一次創(chuàng)建AnimationScope的時(shí)候執(zhí)行一次(或再一下幀執(zhí)行一次,通過(guò)callWithFrameNanos方法)

然后會(huì)判斷如果動(dòng)畫還未執(zhí)行完畢,就一直循環(huán)(while),一幀一幀執(zhí)行doAnimationFrame計(jì)算動(dòng)畫的值

doAnimationFrame方法代碼:

其中通過(guò)時(shí)間等參數(shù)計(jì)算當(dāng)前動(dòng)畫應(yīng)該設(shè)置的值,包括lastFrameTimeNanos和value等屬性,然后再最后調(diào)用updateState方法去將AnimationScope的值更新到AnimationState中

updatState方法代碼:

這個(gè)state對(duì)象其實(shí)也就是animateDpAsState中的Animatable動(dòng)畫類中的AnimationState對(duì)象internalState

所以上面其實(shí)就是Compose中動(dòng)畫的簡(jiǎn)化流程

總結(jié)

由于AnimationState是一個(gè)State,在Compose中使用會(huì)自動(dòng)監(jiān)聽其變化,只要其value變化了,就會(huì)導(dǎo)致相應(yīng)位置重組,然后Composable就會(huì)使用新的值來(lái)展示不同的效果,

比如最開始的示例代碼:

var isOffset by remember { mutableStateOf(false) }
val offsetAnimation by animateDpAsState(targetValue = if (isOffset) 100.dp else 0.dp)
Button(
    onClick = { isOffset = !isOffset },
    modifier = Modifier.offset(0.dp, offsetAnimation)
) {
    Text(text = "點(diǎn)我進(jìn)行位移")
}

在修改了isOffset后,animateDpAsState中的值就會(huì)因?yàn)閯?dòng)畫的計(jì)算和修改內(nèi)部state的value,導(dǎo)致Button的offset函數(shù)一直被重新調(diào)用,使Button不停的向下移動(dòng)

其實(shí)Compose中的動(dòng)畫如果不考慮那么多東西的話,可以簡(jiǎn)化為如下代碼:

    /**
     * creator: lt
     * effect : 自定義的動(dòng)畫播放器,邏輯更簡(jiǎn)單
     * warning:
     * [initialValueWithState]動(dòng)畫要改變的狀態(tài),起始動(dòng)畫值為其value值
     * [targetValue]要通過(guò)動(dòng)畫轉(zhuǎn)化到的目標(biāo)值
     * [duration]動(dòng)畫的持續(xù)時(shí)間
     */
    @OptIn(ExperimentalComposeApi::class)
    suspend fun animateWithFloat(
        initialValueWithState: MutableState<Float>,
        targetValue: Float,
        duration: Int = AnimationConstants.DefaultDurationMillis,
    ) {
        //動(dòng)畫起始值,目標(biāo)差值
        val startValue = initialValueWithState.value
        val valueToBeTransformed = targetValue - startValue
        //動(dòng)畫起始時(shí)間,持續(xù)時(shí)間
        val startTime = System.nanoTime()
        val duration = duration * 1000000L
        //通過(guò)循環(huán)在下一幀計(jì)算動(dòng)畫的值
        val frameClock = coroutineContext.monotonicFrameClock
        while (System.nanoTime() <= startTime + duration) {
            frameClock.withFrameNanos {
                //計(jì)算動(dòng)畫的值,并設(shè)置值給狀態(tài)
                val progress = minOf(it - startTime, duration).toFloat() / duration
                val increase = progress * valueToBeTransformed
                initialValueWithState.value = startValue + increase
            }
        }
    }

使用方式如下,效果跟示例差不多:

ps:不建議線上項(xiàng)目用這個(gè)api,還是用系統(tǒng)的比較好,如果想使用也可以參考(歡迎star): ComposeViews/MAnimator.kt at main · ltttttttttttt/ComposeViews (github.com)

到此這篇關(guān)于Android中分析Jetpack Compose動(dòng)畫內(nèi)部的實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)Android Jetpack Compose內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Android6.0實(shí)現(xiàn)彈出Window提示框

    基于Android6.0實(shí)現(xiàn)彈出Window提示框

    這篇文章主要為大家詳細(xì)介紹了基于Android6.0實(shí)現(xiàn)彈出Window提示框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • Android源碼探究之BaseDexClassLoader的使用

    Android源碼探究之BaseDexClassLoader的使用

    今天解決一個(gè)插件化問題的時(shí)候,竟然發(fā)現(xiàn)SO沒有正常加載,很怪異,最終排查下來(lái)發(fā)現(xiàn)竟然是參數(shù)傳入錯(cuò)誤導(dǎo)致的。這就扯到了本文的標(biāo)題上了,BaseDexClassLoader中的4個(gè)參數(shù)該如何傳入,傳入的又是什么呢
    2022-08-08
  • Flutter 網(wǎng)絡(luò)請(qǐng)求框架封裝詳解

    Flutter 網(wǎng)絡(luò)請(qǐng)求框架封裝詳解

    這篇文章主要介紹了Flutter 網(wǎng)絡(luò)請(qǐng)求框架封裝詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-03-03
  • Android仿QQ可拉伸頭部控件

    Android仿QQ可拉伸頭部控件

    這篇文章主要為大家詳細(xì)介紹了Android仿QQ可拉伸頭部控件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Android使用OKHttp包處理HTTP相關(guān)操作的基本用法講解

    Android使用OKHttp包處理HTTP相關(guān)操作的基本用法講解

    這篇文章主要介紹了Android使用OKHttp包處理HTTP相關(guān)操作的基本用法講解,包括操作如何利用OKHttp操作HTTP請(qǐng)求與處理緩存等內(nèi)容,需要的朋友可以參考下
    2016-07-07
  • Android簽名機(jī)制介紹:生成keystore、簽名、查看簽名信息等方法

    Android簽名機(jī)制介紹:生成keystore、簽名、查看簽名信息等方法

    這篇文章主要介紹了Android簽名機(jī)制介紹:生成keystore、簽名、查看簽名信息等方法,本文講解了升級(jí)App、權(quán)限檢查、生成keystore、對(duì)apk進(jìn)行簽名、查看簽名信息等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • 利用Android實(shí)現(xiàn)比較炫酷的自定義View

    利用Android實(shí)現(xiàn)比較炫酷的自定義View

    自定義View、多線程、網(wǎng)絡(luò),被認(rèn)為是Android開發(fā)者必須牢固掌握的最基礎(chǔ)的三大基本功,這篇文章主要給大家介紹了關(guān)于如何利用Android實(shí)現(xiàn)比較炫酷的自定義View的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • Android實(shí)現(xiàn)調(diào)用攝像頭進(jìn)行拍照功能

    Android實(shí)現(xiàn)調(diào)用攝像頭進(jìn)行拍照功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)調(diào)用攝像頭進(jìn)行拍照功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Android MediaPlayer 音頻倍速播放 調(diào)整播放速度問題

    Android MediaPlayer 音頻倍速播放 調(diào)整播放速度問題

    這篇文章主要介紹了Android MediaPlayer 音頻倍速播放,調(diào)整播放速度,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • android獲取手機(jī)唯一標(biāo)識(shí)的方法

    android獲取手機(jī)唯一標(biāo)識(shí)的方法

    這篇文章主要介紹了獲取安卓的手機(jī)或者平板的唯一標(biāo)識(shí)的方法,需要的朋友可以參考下
    2014-02-02

最新評(píng)論

昭苏县| 霍山县| 互助| 桑日县| 武夷山市| 襄汾县| 汕尾市| 武邑县| 双牌县| 苏尼特左旗| 宜阳县| 加查县| 德昌县| 电白县| 清丰县| 繁昌县| 五华县| 荥阳市| 呼图壁县| 永昌县| 五寨县| 贺兰县| 金塔县| 双桥区| 云和县| 台中县| 合作市| 札达县| 浙江省| 绥滨县| 汉阴县| 巢湖市| 沛县| 贞丰县| 射阳县| 中山市| 防城港市| 法库县| 呈贡县| 乾安县| 宾阳县|