日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Android 使用cos和sin繪制復(fù)合曲線動(dòng)畫(huà)

瀏覽:37日期:2022-09-20 14:59:05
前言

前兩周在開(kāi)發(fā)新需求的時(shí)候,設(shè)計(jì)給了一份類似這樣的動(dòng)畫(huà):

Android 使用cos和sin繪制復(fù)合曲線動(dòng)畫(huà)

看著不難,即使一遍看不懂,嘿嘿,不還有設(shè)計(jì)稿。

Android 使用cos和sin繪制復(fù)合曲線動(dòng)畫(huà)

作為一個(gè)平時(shí)很少寫(xiě)動(dòng)畫(huà)的 Android 開(kāi)發(fā)仔,看到一段段的緩入緩出曲線的設(shè)計(jì)稿時(shí),我的心情是這樣的:

Android 使用cos和sin繪制復(fù)合曲線動(dòng)畫(huà)

雖然,Android 動(dòng)畫(huà)默認(rèn)的插值器 AccelerateDecelerateInterpolator 有這樣緩入緩出的效果:

Android 使用cos和sin繪制復(fù)合曲線動(dòng)畫(huà)

我總不能一整個(gè)動(dòng)畫(huà)給它拆成4段動(dòng)畫(huà)來(lái)寫(xiě),還別說(shuō),我第一次寫(xiě)的代碼還真的是這么干的。

第一次分析

本著能少寫(xiě)一行絕不多寫(xiě)一字的原則,詢問(wèn)了大佬同事的意見(jiàn),大佬大手一揮:PathInterpolator(后證實(shí)有問(wèn)題)。

簡(jiǎn)單看了一下使用方式,需要使用 Path,再看了一眼,好家伙,有可能會(huì)用到貝塞爾曲線,放棄~

為了能夠快速的解決問(wèn)題,就使用了上面談到的方案:

private fun animateTagView(tagView: TextView) { // [0,200]區(qū)間的動(dòng)畫(huà) val valueAnimatorOne = ValueAnimator.ofInt(0, 200) valueAnimatorOne.addUpdateListener { val per = it.animatedValue as Int / 200f tagView.rotation = 4 * per tagView.scaleX = (1 - 0.1 * per).toFloat() tagView.scaleY = (1 - 0.1 * per).toFloat() } valueAnimatorOne.duration = 200 // [200,560]區(qū)間的動(dòng)畫(huà) val valueAnimatorTwo = ValueAnimator.ofInt(200, 560) valueAnimatorTwo.addUpdateListener { val per = (it.animatedValue as Int - 200) / 360f tagView.rotation = 3 - 11 * per tagView.scaleX = (0.9 + 0.1 * per).toFloat() tagView.scaleY = (0.9 + 0.1 * per).toFloat() } valueAnimatorTwo.duration = 360 // [560,840]區(qū)間的動(dòng)畫(huà) val valueAnimatorThree = ValueAnimator.ofInt(560, 840) valueAnimatorThree.addUpdateListener { val per = (it.animatedValue as Int - 560) / 280f tagView.rotation = -8 + 12 * per tagView.scaleX = (1 - 0.2 * per).toFloat() tagView.scaleY = (1 - 0.2 * per).toFloat() } valueAnimatorThree.duration = 280 // [840,1000]的動(dòng)畫(huà) val valueAnimatorFour = ValueAnimator.ofInt(840, 1000) valueAnimatorFour.addUpdateListener { val per = (it.animatedValue as Int - 840) / 160f tagView.rotation = 4 - 4 * per tagView.scaleX = (0.8 + 0.2 * per).toFloat() tagView.scaleY = (0.8 + 0.2 * per).toFloat() } valueAnimatorFour.duration = 160 // 使用AnimatorSet串行執(zhí)行動(dòng)畫(huà) val animationSet = AnimatorSet() animationSet.playSequentially(valueAnimatorOne, valueAnimatorTwo, valueAnimatorThree, valueAnimatorFour) tagView.post { tagView.pivotX = 0f tagView.pivotY = ad_tag_two.measuredHeight.toFloat() animationSet.start() }}

整個(gè)動(dòng)畫(huà)被我拆成了[0,200]、[200,560]、[560,840]和[840,1000]四段屬性動(dòng)畫(huà),因?yàn)楫a(chǎn)品說(shuō)只需要播放一次,所以使用 AnimatorSet 將動(dòng)畫(huà)組裝起來(lái),就可以解決問(wèn)題。

第二次分析

第一次得到的方案雖然能夠解決問(wèn)題,如果遇到循環(huán)播放,AnimatorSet 就不行了,有沒(méi)有其他方案呢?

趁著周末的時(shí)間,學(xué)了一下 PathInterpolator,發(fā)現(xiàn)這個(gè)玩意也解決不了問(wèn)題,或者說(shuō)不好解決問(wèn)題,雖然可以用三階貝塞爾曲線分段畫(huà)出上述曲線,但 PathInterpolator 要求起點(diǎn)和終點(diǎn)分別在 (0,0) 和 (1,1)。

既然插值器不行,可以試試估值器,但一個(gè)估值器也解決不了旋轉(zhuǎn)和縮放兩種動(dòng)畫(huà),看來(lái)得靠 AnimatorUpdateListener 去解決問(wèn)題。

回頭想一下,插值器是將均勻的時(shí)間片段轉(zhuǎn)化成加速或者減速的行為,我們也可以將均勻的時(shí)間片段轉(zhuǎn)化成對(duì)應(yīng)的曲線,只要做好兩點(diǎn):

使用線性的插值器 LinearInterpolator。將上面的曲線拆分,通過(guò)不同的 sin 或者 cos 方法表達(dá)。以旋轉(zhuǎn)動(dòng)畫(huà)為例,拆成的 sin 函數(shù):

Android 使用cos和sin繪制復(fù)合曲線動(dòng)畫(huà)

另外一段動(dòng)畫(huà)的函數(shù)可以參考代碼:

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val tvContent = findViewById<TextView>(R.id.tv_content) val valueAnimatorOne = ValueAnimator.ofFloat(0.0f, 1.5f) valueAnimatorOne.addUpdateListener { // 通過(guò)對(duì)應(yīng)的sin和cos設(shè)置rotation和scale val per = it.animatedValue as Float var rotation: Float = 0f var scale: Float = 0f if(per >= 0 && per < 0.2f){ rotation = sin((per / 0.2f) * Math.PI.toFloat() - Math.PI.toFloat() / 2) * 1.5f + 1.5f scale = cos(per / 0.2f * Math.PI.toFloat()) * 0.05f + 0.95f } if(per >= 0.2f && per < 0.56f){ rotation = sin(Math.PI.toFloat() / 2 + Math.PI.toFloat() * ( per - 0.2f) / 0.36f) * 5.5f - 2.5f scale = cos((per - 0.2f) / 0.36f * Math.PI.toFloat() + Math.PI.toFloat()) * 0.05f + 0.95f } if(per >= 0.56f && per < 0.84f){ rotation = sin(Math.PI.toFloat() * (per - 0.56f) / 0.28f - Math.PI.toFloat() / 2) * 6f - 2f scale = cos((per - 0.56f) / 0.28f * Math.PI.toFloat()) * 0.1f + 0.9f } if(per in 0.84f..1f){ rotation = sin(Math.PI.toFloat() / 2 + Math.PI.toFloat() * (per - 0.84f) / 0.16f ) * 2f + 2f scale = cos((per - 0.84f) / 0.16f * Math.PI.toFloat() + Math.PI.toFloat()) * 0.1f + 0.9f } // 設(shè)置停止時(shí)間 if(per > 1f && per <= 1.5f){ rotation = 0f scale = 1.0f } tvContent.rotation = rotation tvContent.scaleX = scale tvContent.scaleY = scale } // 設(shè)置線性插值器 valueAnimatorOne.interpolator = LinearInterpolator() // 動(dòng)畫(huà)時(shí)間 valueAnimatorOne.duration = 1500 // 無(wú)線循環(huán) valueAnimatorOne.repeatCount = -1 tvContent.post { // 設(shè)置中心點(diǎn) tvContent.pivotX = 0f tvContent.pivotY = tvContent.measuredHeight.toFloat() valueAnimatorOne.start() }}

整個(gè)代碼還是比較簡(jiǎn)單的,旋轉(zhuǎn)動(dòng)畫(huà)曲線由 sin 得出,縮放由 cos 得出,最后改一下中心點(diǎn)。

總結(jié)

本次的動(dòng)畫(huà)案例不難,在面對(duì)復(fù)合緩入緩出曲線的情形,我們可以拆成一段段,用 sin 或者 cos 去描述,這樣的好處是可以只使用一個(gè)屬性動(dòng)畫(huà),且可以循環(huán)播放。

如果你有更好的方案,歡迎評(píng)論區(qū)交流。

以上就是Android 使用cos和sin繪制復(fù)合曲線動(dòng)畫(huà)的詳細(xì)內(nèi)容,更多關(guān)于Android 繪制復(fù)合曲線動(dòng)畫(huà)的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Android
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
波多视频一区| 999久久久91| 亚洲一级大片| 午夜久久福利| 免费观看久久av| 五月天久久网站| 偷拍欧美精品| 亚洲午夜精品久久久久久app| 国产在线观看91一区二区三区 | 秋霞影院一区二区三区| 日韩精品网站| 亚洲激情黄色| 视频一区视频二区中文| 日本不卡中文字幕| 国产乱码精品一区二区三区四区| 国产精品视频一区二区三区四蜜臂| 欧美午夜三级| 欧美国产不卡| 超碰在线99| 亚洲va中文在线播放免费| 99久久99久久精品国产片果冰 | 欧美日韩视频免费观看| 日韩一级网站| 日韩高清不卡一区二区| 久久国产精品免费一区二区三区| 久久99久久久精品欧美| 国内自拍视频一区二区三区| 日韩在线二区| 国产亚洲精品v| 丝袜美腿高跟呻吟高潮一区| 国产欧美午夜| 韩日一区二区| 国产在线成人| 婷婷亚洲成人| 精品九九久久| 一区二区三区四区在线看| 久久亚洲欧美| 乱一区二区av| 美女网站一区| 日本天堂一区| 日产精品一区| 日韩欧美中文字幕在线视频| 日本激情一区| 蜜臀精品一区二区三区在线观看 | 精品久久在线| 欧美一区二区三区高清视频| 亚洲精选av| 国产va免费精品观看精品视频| 在线国产一区| 国产欧美日韩精品高清二区综合区 | 美女视频网站久久| 亚洲成人精选| 国产欧美日韩精品高清二区综合区| 成年男女免费视频网站不卡| 免费在线观看成人| 国产一区二区三区不卡av| 欧美日韩日本国产亚洲在线| 精品一区视频| 日韩专区在线视频| 精品国产乱码久久久| 欧美综合二区| 国产理论在线| 日韩国产一二三区| 99久久夜色精品国产亚洲1000部| 日韩欧美精品一区二区综合视频| 成人日韩在线观看| 国产精品中文| 99精品99| 久久毛片亚洲| 97久久超碰| 欧美日韩国产高清电影| 久久av导航| 亚洲尤物av| 欧美亚洲激情| www.九色在线| 国产福利亚洲| 亚洲资源在线| 国内精品福利| 成人台湾亚洲精品一区二区 | 久久aⅴ国产紧身牛仔裤| 欧美丰满日韩| 日本色综合中文字幕| 自拍日韩欧美| 天堂av在线| 麻豆国产91在线播放| 四虎在线精品| 99视频一区| 韩国三级一区| 国产一区二区三区四区五区| 日本在线一区二区三区| 丝袜诱惑制服诱惑色一区在线观看 | 国产精品亚洲欧美| 蜜臀av国产精品久久久久| 久久狠狠婷婷| 国产精品99一区二区三| 欧美一区影院| 免费美女久久99| 亚洲精品1区2区| 亚洲天堂黄色| 亚洲va中文在线播放免费| 精品日韩一区| 国产情侣久久| 日本不卡高清视频| 免费在线观看视频一区| 欧美日韩精品一区二区视频| 成人一区而且| 国产+成+人+亚洲欧洲在线| 欧美日韩精品一区二区三区在线观看| 亚洲精品在线a| 免费久久精品视频| 视频一区中文字幕国产| 亚洲主播在线| 国产亚洲午夜| 久久电影一区| 亚洲欧美日本国产专区一区| 午夜欧美精品| 国产亚洲高清视频| 99热精品在线观看| 在线亚洲精品| 99xxxx成人网| 中文日韩在线| 久久99伊人| 日本欧美在线看| 视频一区免费在线观看| 久久大逼视频| 日日夜夜免费精品| 欧美日韩 国产精品| 欧美伊人影院| 欧美国产极品| 精品国产99| 日韩电影二区| 久久视频国产| 9色精品在线| 亚洲一区二区三区久久久| 中文日韩在线| 中文字幕日本一区二区| 欧美一级一区| 欧美一区二区三区久久精品| 国产精品久久久久久久久免费高清 | 国产日韩免费| 性欧美69xoxoxoxo| 色狠狠一区二区三区| 国产美女视频一区二区| 欧美91在线|欧美| 91亚洲自偷观看高清| 高清av不卡| 五月天综合网站| 亚洲一区二区三区四区电影| 日韩一区二区三区精品视频第3页| 日韩和欧美的一区| 国产一区日韩| 九九久久电影| 天堂精品久久久久| 精品国产鲁一鲁****| 视频小说一区二区| 亚洲综合精品| 国产精品麻豆成人av电影艾秋| 福利片在线一区二区| 亚洲性图久久| 亚洲三级精品| 国产黄色一区| 欧美成人综合| 免费精品视频最新在线| 欧美激情视频一区二区三区免费| 日韩精品麻豆| 蜜桃视频在线观看一区| 欧美激情 亚洲a∨综合| 在线成人直播| 国产欧美日韩影院| 欧美aa在线观看| 美国三级日本三级久久99 | 日韩中文字幕亚洲一区二区va在线| 日本免费在线视频不卡一不卡二| 久久亚洲国产精品尤物| 婷婷综合在线| 久久国产精品美女| 美女网站一区| 久久国产三级| 激情久久久久久| 欧美日韩一区二区国产| 另类中文字幕国产精品| 日韩国产高清在线| 日本精品影院| 日韩国产在线一| 国产专区一区| 欧美日韩调教| 国产字幕视频一区二区| 国产麻豆一区二区三区| 久久精品国语| 日韩精品乱码av一区二区| 日韩在线看片| 日韩av中文字幕一区二区| 三级精品视频| 国产精品一区免费在线| 欧美福利一区| 精品一区二区三区视频在线播放| 国产精品视区| av日韩中文| 欧美亚洲色图校园春色| 午夜宅男久久久|