<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ConstraintLayout2.0一篇寫不完之Stagger交錯(cuò)

          共 4306字,需瀏覽 9分鐘

           ·

          2021-09-08 10:05

          點(diǎn)擊上方藍(lán)字關(guān)注我,知識(shí)會(huì)給你力量


          在Flutter中,有個(gè)StaggerAnimation,可以實(shí)現(xiàn)交錯(cuò)動(dòng)畫效果,這個(gè)效果相當(dāng)于在申明式編程中為多個(gè)動(dòng)畫增加了多條時(shí)間線,在Android中,以往要實(shí)現(xiàn)交錯(cuò)動(dòng)畫效果,需要為每個(gè)屬性動(dòng)畫設(shè)置Delay時(shí)間,或者監(jiān)聽其生命周期,而在MotionLayout中,可以直接在xml中設(shè)置交錯(cuò)動(dòng)畫的驅(qū)動(dòng)流程,極大的簡(jiǎn)化了動(dòng)畫的創(chuàng)建。

          在MotionLayout中,它為每個(gè)被標(biāo)記了motionStagger的View分配了一個(gè)float value(沒有標(biāo)記的View不會(huì)被引入交錯(cuò)動(dòng)畫),float value最小的(V0)的View首先被啟動(dòng)。float value最高的(Vn)的View最后啟動(dòng)。

          這是motionStagger的動(dòng)畫總綱,但是具體的啟動(dòng)時(shí)間和執(zhí)行順序,由下面的這些參數(shù)來精確控制。

          • MotionLayout中每個(gè)VIew的motionStagger value被標(biāo)記為S(Vi)
          • 總的Stagger Value被標(biāo)記為stagger,取值為0.0-1.0,通常在Transition中指定
          • 在Transition中指定動(dòng)畫的duration

          在這基礎(chǔ)上,motionStagger定義了下面兩條規(guī)則:

          • View的動(dòng)畫持續(xù)時(shí)長(zhǎng) = duration * (1 - stagger)
          • View的動(dòng)畫啟動(dòng)時(shí)間點(diǎn)算法為:duration * (stagger - stagger * (S(Vi) - S(V0)) / (S(Vn) - S(V0)))

          其中最奇怪的就是這個(gè)參數(shù):(S(Vi) - S(V0)) / (S(Vn) - S(V0))

          我們可以梳理下,我們給MotionLayout中的所有需要做StaggerAnimation的View標(biāo)記了motionStagger value,這些元素形成了一個(gè)數(shù)組,從大到小進(jìn)行排序:

          【Sv0—Sv1—Sv2—Sv3—Sv4—Sv5】

          在這個(gè)數(shù)組只,(S(Vi) - S(V0)) / (S(Vn) - S(V0))這個(gè)表達(dá)式所具有的幾何含義是什么呢?實(shí)際上就是點(diǎn)陣的Manhattan distance(曼哈頓距離),具體如下所示。

          image-20210830144923418

          好了,看到這里還不走的朋友,心里也忍不住會(huì)想了,這TM是什么鬼?我寫個(gè)動(dòng)畫還TM要這些??

          是的,有的復(fù)雜,我們先舉個(gè)例子來看下。

          首先,我假定設(shè)置MotionLayout中有3個(gè)View——View1、View2、View3,分別設(shè)置motionStagger value為7,5,3,再給Transition設(shè)置staggered為0.6,duration為5000,這些都是我假設(shè)的,我們來看下這個(gè)狀態(tài)下,MotionLayout的StaggerAnimation是如何創(chuàng)建的。

          首先,計(jì)算duration。

          View的動(dòng)畫持續(xù)時(shí)長(zhǎng) = duration * (1 - stagger)
          即:View的動(dòng)畫持續(xù)時(shí)長(zhǎng) = 5000 * (1 - 0.6) = 2000

          接下來,針對(duì)每個(gè)View計(jì)算,所以,Sv1= 7,Sv2= 5,Sv3= 3。

          duration * (stagger - stagger * (S(Vi) - S(V0)) / (S(Vn) - S(V0)))
          即:
          View1:?jiǎn)?dòng)于 5000 * (0.6 - 0.6 * (7 - 3)/(7 - 3)) = 0
                 終止于 0 + 2000 = 2000

          View2:?jiǎn)?dòng)于 5000 * (0.6 - 0.6 * (5 - 3)/(7 - 3)) = 1500
                 終止于 1500 + 2000 = 3500
                 
          View3:?jiǎn)?dòng)于 5000 * (0.6 - 0.6 * (3 - 3)/(7 - 3)) = 3000
                 終止于 3000 + 2000 = 5000

          是不是有點(diǎn)意思。

          我感覺沒意思,難道我寫動(dòng)畫還要這樣湊數(shù)字嗎?

          如果我們要從正向來理解這些公式的含義,那么要將上面的公式進(jìn)行一下變形處理。

          startPoint = duration * (stagger - stagger * (S(Vi) - S(V0)) / (S(Vn) - S(V0)))

          再理清楚一點(diǎn):

          animationStartTime = totalDuration * (stagger - stagger * ((staggerCurrentView - lowestStaggerValue)/(highestStaggerValue - lowestStaggerValue))

          totalDuration好說,剩下的就是stagger值的確定了。

          我們同樣用之前那個(gè)例子,我假定設(shè)置MotionLayout中有3個(gè)View——View1、View2、View3,三個(gè)View依次出現(xiàn)。

          前面我們的公式指出了:viewDuration = totalDuration * (1 - stagger),那么將其變形處理后,我們就得到了stagger:

          stagger = 1 - (viewDuration / totalDuration)

          所以,如果我要三個(gè)動(dòng)畫依次出現(xiàn),那么viewDuration / totalDuration就是1/3,也就是說stagger約為0.6。

          確定了stagger之后,我們?cè)賮砜磀uration,由于stagger確定,所以totalDuration可以自由設(shè)置,viewDuration會(huì)根據(jù)其它兩個(gè)參數(shù)動(dòng)態(tài)變化。

          那么每個(gè)View的motionStagger呢?實(shí)際上在開發(fā)動(dòng)畫的時(shí)候,通常都是先使用遞減數(shù)列或者遞增數(shù)列來做(取決于你的視圖展示順序),再根據(jù)動(dòng)畫參數(shù)進(jìn)行微調(diào),例如前面的例子,我們可以給View1、2、3分別設(shè)置motionStagger為3、2、1,那么啟動(dòng)順序如下所示。

          totalDuration = 5000,stagger = 0.6,viewDuration = 2000
          即:
          View1:?jiǎn)?dòng)于 5000 * (0.6 - 0.6 * (3 - 1)/(3 - 1)) = 0
                 終止于 0 + 2000 = 2000

          View2:?jiǎn)?dòng)于 5000 * (0.6 - 0.6 * (2 - 1)/(3 - 1)) = 1500
                 終止于 1500 + 2000 = 3500
                 
          View3:?jiǎn)?dòng)于 5000 * (0.6 - 0.6 * (1 - 1)/(3 - 1)) = 3000
                 終止于 3000 + 2000 = 5000

          有沒有發(fā)現(xiàn),和前面的結(jié)果是一致的!

          越來越難了不是嗎,寫個(gè)動(dòng)畫還得用這么多數(shù)學(xué)公式!

          其實(shí)不用。

          最后我們來總結(jié)下,一句話讓你了解Stagger。

          ?

          當(dāng)MotionLayout中的所有View的motionStagger value遞增或者遞減時(shí),在Transition中設(shè)置的staggered控制的就是每個(gè)View啟動(dòng)的時(shí)間間隔,staggered value越小,間隔越短,極端下,為0時(shí),沒有Stagger效果,為1時(shí),每個(gè)View動(dòng)畫完成后才執(zhí)行下一個(gè)。

          ?

          以上。

          當(dāng)然,你不懂這些公式也能寫,但是懂了能讓你寫的更清晰,這就是「湊」和「算」的區(qū)別。

          向大家推薦下我的網(wǎng)站 https://xuyisheng.top/  點(diǎn)擊原文一鍵直達(dá)

          專注 Android-Kotlin-Flutter 歡迎大家訪問



          往期推薦


          本文原創(chuàng)公眾號(hào):群英傳,授權(quán)轉(zhuǎn)載請(qǐng)聯(lián)系微信(Tomcat_xu),授權(quán)后,請(qǐng)?jiān)谠瓌?chuàng)發(fā)表24小時(shí)后轉(zhuǎn)載。
          < END >
          作者:徐宜生

          更文不易,點(diǎn)個(gè)“三連”支持一下??


          瀏覽 43
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人视频黄片 | 无码免费一区二区三区在线 | 老司机福利在线视频 | 亚洲最大黄色 | 亚洲黄色片免费看 |