【Flutter 組件集錄】AnimatedContainer | 8 月更文挑戰

張風捷特烈 2021-08-15 18:14:25 阅读数:279

本文一共[544]字,预计阅读时长:1分钟~
flutter animatedcontainer
前言:

這是我參與8月更文挑戰的第 15 天,活動詳情查看:8月更文挑戰。為應掘金的八月更文挑戰,我准備在本月挑選 31 個以前沒有介紹過的組件,進行全面分析和屬性介紹。這些文章將來會作為 Flutter 組件集錄 的重要素材。希望可以堅持下去,你的支持將是我最大的動力~

本系列 組件文章 列錶
1.NotificationListener 2.Dismissible 3.Switch
4.Scrollbar 5.ClipPath 6.CupertinoActivityIndicator
7.Opacity 8.FadeTransition 9. AnimatedOpacity
10. FadeInImage 11. Offstage 12. TickerMode
13. Visibility 14. Padding 15. AnimatedContainer[本文]

一、認識 AnimatedContainer 組件

Container 組件 一文中,我們知道它存在的價值是:整合如下 8 個單子組件,這樣通過一個 Container 完成多種功能。可以避免在使用是層層嵌套,簡化代碼結構。而 AnimatedContainer 就相當於一個加强版的 Container ,可以讓其中的各個屬性在變化時具有動畫效果


1.AnimatedContainer 基本信息

AnimatedContainer 是一個隱式動畫組件,和之前介紹過的 AnimatedOpacity 是同類,這種動畫組件,只需要更改屬性 + 重新構建 就可以實現動畫。這類的動畫組件,都有一些共同的屬性,如 duration 錶示動畫時長、curve 錶示動畫曲線、onEnd 錶示動畫結束的回調。

下面可以對比一下 AnimatedContainerContainer 的屬性,可以看出基本是一模一樣的。也就是說了解 Container 屬性的用法之後,其實 AnimatedContainer 自然也就會了。兩者的區別只在於:Container 在屬性變化重構後,是直接變換,而 AnimatedContainer 是動畫漸變。


2. AnimatedContainer 組件的使用

我們先通過一個簡單的例子看一下 AnimatedContainer 的使用方式。如下,當點擊按鈕時,通過 _changeSize 方法改變寬高數值,並重建組件。可以看出 AnimatedContainer 尺寸變化會有動畫效果。想一下,如果這裏使用 Container 組件,那麼將會直接改變到對應數值,就比較生硬。

class AnimatedContainerDemo extends StatefulWidget {
@override
_AnimatedContainerDemoState createState() => _AnimatedContainerDemoState();
}
class _AnimatedContainerDemoState extends State<AnimatedContainerDemo> {
double _width = 180;
double _height = 120;
@override
Widget build(BuildContext context) {
return Wrap(
direction: Axis.vertical,
crossAxisAlignment: WrapCrossAlignment.center,
children: <Widget>[
ElevatedButton(
child: const Text('更新寬高'),
onPressed: _changeSize,
),
const SizedBox(height: 10,),
buildAnimatedContainer()
],
);
}
Widget buildAnimatedContainer() => AnimatedContainer(
duration: const Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
height: _height,
color: Colors.black12,
width: _width,
onEnd: onEnd,
);
void onEnd() {
print('End');
}
void _changeSize() {
setState(() {
_width = _width == 100 ? 180 : 100;
_height = _height == 100 ? 120 : 100;
});
}
}
複制代碼

3.AnimatedContainer 組件的其他屬性

AnimatedContainer 的其他某些屬性也可以進行動畫,比如下面的 alignmentcolor 。和寬高一樣,只需要改變屬性值重構組件,就能進行動畫。不需要處理動畫器,這就是隱式動畫的方便之處。

Alignment _alignment = Alignment.topLeft;
Color _color = Colors.orange;
Widget buildAnimatedContainer() => AnimatedContainer(
duration: const Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
height: 100,
color: _color.withOpacity(0.2),
width: 100,
alignment: _alignment,
onEnd: onEnd,
child: FlutterLogo(),
);
void _change() {
setState(() {
_alignment =
_alignment == Alignment.center ?
Alignment.topLeft : Alignment.center;
_color = _color == Colors.orange ?
Colors.purple : Colors.orange;
});
}
複制代碼

我們也可以對 decoration 屬性進行動畫,如下的圓角和陰影裝飾,也是只需要改變屬性值重構組件 即可。

總的來說 AnimatedContainer 的屬性意義和 Container 一模一樣,只是前者在屬性變化重構時會進行動畫過渡到該值。這樣會使變化顯得不那麼突兀,視覺上更好些。其他的屬性參考 Container 組件 一文,大家可以自己試試改變這些屬性的效果。


二、AnimatedContainer 的源碼實現

AnimatedContainer 繼承自 ImplicitlyAnimatedWidget ,這也就說明它和 AnimatedOpacity 是同族的,所以他們在源碼實現上是類似的。


不同點在於AnimatedOpacity 是通過 FadeTransition 組件實現的動畫漸變功能,該組件天生可以監聽 Listenable 對象觸發重繪。而 _AnimatedContainerState 繼承自 AnimatedWidgetBaseState

AnimatedWidgetBaseState 中會監聽動畫控制器 controller ,通過 setState 對子組件進行 局部更新。其原理和 AnimatedBuilder 是一致的。


從狀態類中維護的 XXXTween 可以看出能够進行動畫的屬性有哪些。從組件的構建中可以看出,本身還是使用了 Container 實現的。由於之前監聽了動畫,並執行setState ,那麼在動畫的每一幀,都會更新 Container 的屬性配置信息,進行局部更新


最後,動畫的開啟和 AnimatedOpacity 一文中介紹的一樣,比較他們都是 ImplicitlyAnimatedWidget 。動畫器的維護都封裝在 ImplicitlyAnimatedWidgetState 中:

StatefulWidget重新構建時,狀態類是不會重新初始化的。而是觸發 State#didUpdateWidget 來通知 Widget 配置的變更,在此可以處理一下組件更新的邏輯。可以看出,如下在 didUpdateWidget 中,會對配置進行對比,發生變化將會更新。最後 _controller 會執行 forward 進行動畫。

AnimatedContainer 的使用方式到這裏就介紹完畢,那本文到這裏就結束了,謝謝觀看,明天見~

版权声明:本文为[張風捷特烈]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/08/20210815181418975q.html