Flutter實(shí)現(xiàn)笑嘻嘻的動(dòng)態(tài)表情的示例代碼
前言
身在孤島有很多無(wú)奈,比如說(shuō)程序員屬于比較偏門的職業(yè)。尤其是早些年,在行業(yè)里跳過(guò)幾次槽后,可能你就已經(jīng)認(rèn)識(shí)整個(gè)圈子的人了。然后,再跳槽很可能就再次“偶遇”前同事了,用大潘的口頭語(yǔ)來(lái)說(shuō)就是:“好尷尬呀”。因此, 問(wèn)起職業(yè),往往只能是回答是搞計(jì)算機(jī)的。結(jié)果可能更尷尬,問(wèn)的人可能笑嘻嘻地瞅著你,像看怪物一樣看著你,接著突然冒出一句靈魂拷問(wèn):“我家電腦壞了,你能修不?”不過(guò)也不奇怪,那個(gè)時(shí)候在島上重裝一個(gè) Windows XP 系統(tǒng)都需要100大洋。唉,當(dāng)初后悔沒(méi)在中關(guān)村的鼎好多學(xué)習(xí)攢機(jī)技術(shù)……
image.png
這個(gè)印象太深刻,本篇我們就用動(dòng)畫復(fù)現(xiàn)一下這種表情,效果如下圖所示。
笑臉動(dòng)畫.gif
AnimatedContainer 介紹
在實(shí)現(xiàn)之前,先介紹一個(gè)新組件 —— AnimatedContainer
??催@個(gè)名字就知道和 Container
有關(guān),實(shí)際上AnimatedContainer
是 Flutter 中的一個(gè)動(dòng)畫容器,Container
有的屬性基本上它都有,我們看一下二者的構(gòu)造方法的區(qū)別。
AnimatedContainer({ ????Key??key, ????this.alignment, ????this.padding, ????Color??color, ????Decoration??decoration, ????this.foregroundDecoration, ????double??width, ????double??height, ????BoxConstraints??constraints, ????this.margin, ????this.transform, ????this.transformAlignment, ????this.child, ????this.clipBehavior?=?Clip.none, ????Curve?curve?=?Curves.linear, ????required?Duration?duration, ????VoidCallback??onEnd, ??}); Container({ ????Key??key, ????this.alignment, ????this.padding, ????this.color, ????this.decoration, ????this.foregroundDecoration, ????double??width, ????double??height, ????BoxConstraints??constraints, ????this.margin, ????this.transform, ????this.transformAlignment, ????this.child, ????this.clipBehavior?=?Clip.none, ??});
可以看到,實(shí)際上 AnimatedContainer
和 Container
只差了3個(gè)屬性,而這三個(gè)屬性就是控制動(dòng)畫的參數(shù):
curve
:動(dòng)畫曲線,默認(rèn)是線性;duration
:動(dòng)效時(shí)長(zhǎng)參數(shù);onEnd
:動(dòng)效結(jié)束后的回調(diào)方法。
AnimatedContainer
的特性是所有涉及外觀的屬性都會(huì)生成一個(gè)過(guò)渡動(dòng)效,當(dāng)這些外觀屬性發(fā)生改變的時(shí)候就會(huì)使用生成的的動(dòng)效來(lái)完成過(guò)渡,從而展現(xiàn)出動(dòng)畫效果。像我們要實(shí)現(xiàn)的笑嘻嘻的表情其實(shí)就是利用 AnimatedContainer
實(shí)現(xiàn)的。
組件結(jié)構(gòu)
我們的笑嘻嘻動(dòng)效,底部是一個(gè)圓形腦袋,上面有兩顆眼睛和一個(gè)嘴巴,其中眼睛和嘴巴有移動(dòng)動(dòng)效,而眼睛的眼珠還有方向的動(dòng)效。這些動(dòng)效都可以使用AnimatedContainer
來(lái)實(shí)現(xiàn)。大的頁(yè)面結(jié)構(gòu)如下:
細(xì)節(jié)實(shí)現(xiàn)
腦袋這個(gè)很容易,直接用原型裁剪,設(shè)置尺寸和底色即可:
//?腦袋 ClipOval( ??child:?Container( ????width:?120, ????height:?120, ????color:?Colors.blue, ??), ),
眼睛左眼和右眼有點(diǎn)不一樣,眼球?qū)嶋H就是AnimatedContainer
使用 borderRadius
裁剪為圓形,而眼珠是AnimatedContainer
的子組件 —— 黑色的圓圈。具體實(shí)現(xiàn)向左或向右看使用一個(gè)變量 seeLeft
控制,而向左向右的轉(zhuǎn)換過(guò)渡效果都由 AnimatedContainer
控制。
seeLeft = true
,向左看:眼珠對(duì)齊的方式是bottomLeft
,左眼縱向方向上稍微往下移一點(diǎn);右眼往左移動(dòng)一定的位置,這樣就會(huì)有向左看的效果了;seeLeft = false
,向右看:眼珠對(duì)齊的方式是bottomRight
,右眼縱向方向上稍微往下移一點(diǎn);左眼往右移動(dòng)一定的位置,這樣就會(huì)有向右看的效果了;
實(shí)現(xiàn)代碼如下:
//?左眼 Positioned( ??top:?marginTop, ??left:?marginLR, ??child:?AnimatedContainer( ????alignment: ????????seeLeft???Alignment.bottomLeft?:?Alignment.bottomRight, ????padding:?EdgeInsets.all(eyePadding), ????transform:?Matrix4.identity() ??????..translate( ??????????seeLeft???0.0?:?sideOffset,?seeLeft???eyeOffset?:?0.0,?0), ????duration:?Duration(seconds:?1), ????curve:?Curves.fastOutSlowIn, ????width:?eyeSize, ????height:?eyeSize, ????decoration:?BoxDecoration( ??????color:?Colors.white, ??????borderRadius:?BorderRadius.circular(eyeSize?/?2), ????), ????child:?ClipOval( ??????child:?Container( ????????color:?Colors.black, ????????width:?eyeBallSize, ????????height:?eyeBallSize, ??????), ????), ??), ), //?右眼 Positioned( ??top:?marginTop, ??right:?marginLR, ??child:?AnimatedContainer( ????alignment: ????????seeLeft???Alignment.bottomLeft?:?Alignment.bottomRight, ????padding:?EdgeInsets.all(eyePadding), ????transform:?Matrix4.identity() ??????..translate(seeLeft???-sideOffset?:?0.0, ??????????seeLeft???0.0?:?eyeOffset,?0), ????duration:?Duration(seconds:?1), ????curve:?Curves.fastOutSlowIn, ????width:?eyeSize, ????height:?eyeSize, ????decoration:?BoxDecoration( ??????color:?Colors.white, ??????borderRadius:?BorderRadius.circular(eyeSize?/?2), ????), ????child:?ClipOval( ??????child:?Container( ????????color:?Colors.black, ????????width:?eyeBallSize, ????????height:?eyeBallSize, ??????), ????), ??), ),
這里的眼珠對(duì)齊使用的就是AnimatedContainer
的 alignment
參數(shù)控制,而眼球的位置使用 Matrix4
的平移實(shí)現(xiàn):
Matrix4.identity() ??..translate(seeLeft???-sideOffset?:?0.0,?seeLeft???0.0?:?eyeOffset,?0),
笑臉的實(shí)現(xiàn)使用ClipPath
,繪制兩條弧線就可以了,然后平移的幅度和眼珠保持一致,就可以感覺(jué)是轉(zhuǎn)頭的效果了,AnimatedContainer
部分的代碼如下:
//?笑嘻嘻的嘴巴 Positioned( ??bottom:?10, ??height:?40, ??left:?0, ??child:?AnimatedContainer( ????alignment: ????????seeLeft???Alignment.bottomLeft?:?Alignment.bottomRight, ????padding:?EdgeInsets.all(4.0), ????transform:?Matrix4.identity() ??????..translate(seeLeft???25.0?:?35.0,?0,?0), ????duration:?Duration(seconds:?1), ????curve:?Curves.fastOutSlowIn, ????child:?ClipPath( ??????clipper:?SmileClipPath(), ??????child:?Container( ????????width:?60, ????????height:?40, ????????color:?Colors.yellow, ??????), ????), ??), ),
笑嘻嘻的嘴巴的裁剪類 SmileClipPath
代碼如下:
class?SmileClipPath?extends?CustomClipper<Path>?{ ??@override ??Path?getClip(Size?size)?{ ????return?Path() ??????..moveTo(0,?0) ??????..arcToPoint( ????????Offset(size.width,?0), ????????radius:?Radius.circular(size.width?*?0.55), ????????clockwise:?false, ??????) ??????..arcToPoint( ????????Offset(0,?0), ????????radius:?Radius.circular(size.width), ????????clockwise:?true, ??????); ??} ??@override ??bool?shouldReclip(covariant?CustomClipper<Path>?oldClipper)?{ ????return?false; ??} }
最后,控制狀態(tài)變量 seeLeft
的變化通過(guò)一個(gè)按鈕點(diǎn)擊觸發(fā)就好了。
floatingActionButton:?FloatingActionButton( ??child:?Icon(Icons.play_arrow,?color:?Colors.white), ??onPressed:?()?{ ????setState(()?{ ??????seeLeft?=?!seeLeft; ????}); ??}, ),
最終運(yùn)行效果如下,完整代碼已提交至:動(dòng)畫相關(guān)代碼。
笑臉動(dòng)畫.gif
總結(jié)
本篇主要介紹 AnimatedContainer
的使用,對(duì)于要對(duì) Container
實(shí)現(xiàn)動(dòng)效的場(chǎng)合,可以直接使用AnimatedContainer
進(jìn)行替換,然后通過(guò)更改AnimatedContainer
的屬性就可以實(shí)現(xiàn)過(guò)渡動(dòng)效了。比如官網(wǎng)就搞了個(gè)隨機(jī)的形狀、弧度和顏色的動(dòng)效,看著也挺有趣的。
AnimatedContainer 官方動(dòng)效.gif
以上就是Flutter實(shí)現(xiàn)笑嘻嘻的動(dòng)態(tài)表情的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Flutter動(dòng)態(tài)表情的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
android實(shí)現(xiàn)菜單三級(jí)樹效果
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)菜單三級(jí)樹效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11Android實(shí)現(xiàn)簡(jiǎn)單的加載進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡(jiǎn)單的加載進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05android studio使用SQLiteOpenHelper()建立數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了android studio使用SQLiteOpenHelper()建立數(shù)據(jù)庫(kù)的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03通過(guò)OpenGL ES混合模式縮放視頻緩沖區(qū)來(lái)適應(yīng)顯示尺寸
當(dāng)開發(fā)基于軟件模式的游戲時(shí),通過(guò)縮放視頻緩沖區(qū)來(lái)適應(yīng)顯示尺寸是最棘手的問(wèn)題之一;作為開發(fā)人員,我們必須嘗試在性能與顯示質(zhì)量之間找到最佳平衡點(diǎn)2012-12-12Android Studio實(shí)現(xiàn)格式化XML代碼順序
這篇文章主要介紹了Android Studio實(shí)現(xiàn)格式化XML代碼順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03Android編程中context及全局變量實(shí)例詳解
這篇文章主要介紹了Android編程中context及全局變量的用法,結(jié)合實(shí)例形式較為詳細(xì)的分析講述了context及全局變量的使用技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2015-12-12Android仿美團(tuán)分類下拉菜單實(shí)例代碼
這篇文章主要為大家詳細(xì)介紹了Android仿美團(tuán)分類下拉菜單實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05Flutter開發(fā)之設(shè)置應(yīng)用名稱及圖標(biāo)的教程
這篇文章主要介紹了Flutter設(shè)置應(yīng)用名稱及圖標(biāo)的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Android?drawFunctor?原理及應(yīng)用詳情
這篇文章主要介紹了Android?drawFunctor原理及應(yīng)用詳情,drawFunctor是Android提供的一種在RenderThread渲染流程中插入執(zhí)行代碼機(jī)制,更多相關(guān)內(nèi)容需要的小伙伴可以參考一下2022-08-08Android開發(fā)模仿qq視頻通話懸浮按鈕(實(shí)例代碼)
這篇文章主要介紹了Android開發(fā)模仿qq視頻通話懸浮按鈕功能的實(shí)例代碼,需要的的朋友參考下2017-02-02