先來看圖:git
咱們在平常使用 APP 當中,確定會遇到這種效果,那麼這種效果是如何實現的呢?github
首先仍是老套路,先肯定一下需求,捋一下思路,而後纔好寫代碼:bash
捋好了思路,下面咱們來開始實現。微信
首先有一個圓,這個圓應該怎麼畫?我想到了兩種方案:async
這兩種方式都很簡單,因此我選擇了後者,由於後者更簡單(23333)。動畫
代碼我就不貼了,不過代碼我已經提交到了github.com/wanglu1209/…,能夠隨時查看。ui
一邊擴散,一邊消失。this
有沒有想起來我上一篇文章提及的箭頭小Demo? --- Flutter | 經過一個小例子帶你認識動畫 Animationlua
沒錯,這裏也是使用這種 evaluate
來計算大小和透明度。spa
代碼以下:
Container(
width: _radiusTween.evaluate(animation),
height: _radiusTween.evaluate(animation),
child: ClipOval(
child: Opacity(
opacity: _opacityTween.evaluate(animation),
child: Container(
color: color,
),
),
),
)
複製代碼
這樣,咱們只須要設置好該 Tween 的 begin 和 end 就能實現一邊擴散,一邊消失了。
首先,咱們都知道,在 Flutter 當中,如何把一個 widget 浮在另外一個 widget 上。沒錯,用 Stack
。
那就要建立一個 List<Widget>
來存放咱們的剛纔定義好的「會擴散消失的圓」。
並且咱們也知道,這個「會擴散消失的圓」須要一個 Animation
,那也就是說每個圓都須要一個Animation
和 AnimationController
,那咱們也須要建立一個 List<AnimationController>
來控制每個「會擴散消失的圓」。
而且,在 AnimationStatus
== completed
的時候,把該 圓移除,而且把該 controller dispose。
並且在該 Widget dispose 的時候,也應該把全部未清除的 controller 給清除掉。
大體代碼以下:
int i = 0;
while (widget.cycles == null ? true : i < widget.cycles) {
if (mounted) {
setState(() {
AnimationController _animationController;
Animation<double> _animation;
_animationController =
AnimationController(vsync: this, duration: widget.duration);
_animation = CurvedAnimation(
parent: _animationController, curve: Curves.linear);
_animationController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
children.removeAt(0);
controllers.removeAt(0);
_animationController.dispose();
}
});
controllers.add(_animationController);
_animationController.forward();
widget.child != null
? children.insert(
children.length - 1,
AnimatedSpread(
animation: _animation,
radius: widget.radius,
maxRadius: widget.maxRadius,
color: widget.spreadColor,
))
: children.add(AnimatedSpread(
animation: _animation,
radius: widget.radius,
maxRadius: widget.maxRadius,
color: widget.spreadColor,
));
});
}
if (widget.cycles != null) i++;
await Future.delayed(
Duration(milliseconds: widget.duration.inMilliseconds ~/ 3));
}
複製代碼
每個 animation
是有 duration 的,那麼咱們就能夠根據該持續時間來設置何時出現第二個圓,我這裏寫的是持續時間的 1/3。
這樣看起來效果是不錯的。
在剛纔的代碼裏面其實就有這一部分的邏輯:
while (widget.cycles == null ? true : i < widget.cycles) {
// ...
}
複製代碼
這裏主要就是控制顯示幾回,畢竟有的需求不是一直顯示波紋效果。
我這裏寫的 child 默認形狀是圓形的,大小被 SizedBox
控制爲 radius
的大小:
ClipOval(
child: SizedBox(
width: widget.radius,
height: widget.radius,
child: widget.child,
),
),
複製代碼
若是有 child 的話如何保證 child 永遠都是在最上面?
只須要在插入圓形的時候使用 List.insert(index, element)
方法就ok了。
這樣一個有水波紋擴散效果的 Widget 就封裝完成了。
這裏我使用了和上篇文章同樣的邏輯,都是使用的 AnimatedWidget
,
而後用 Stack
來包裝,Future.delayed
來控制下一個圓形出現的時間。
另我我的建立了一個「Flutter 交流羣」,能夠添加我我的微信 「17610912320」來入羣。
推薦閱讀:
Flutter | 經過一個小例子帶你認識動畫 Animation