Flutter中 隐式动画组件
Flutter隐式动画组件是一组能自动处理动画过渡的特殊Widget,开发者只需设置目标值即可自动创建和管理动画过程。这些组件分为容器布局类(如AnimatedContainer、AnimatedPadding)、视觉外观类(如AnimatedOpacity、AnimatedTheme)、变换类(如AnimatedScale、AnimatedRotation)以及列表网格类(如AnimatedLi
本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
隐式动画组件是 Flutter 中一组特殊的 Widget,它们能够自动处理动画过渡。只需要设置目标值,组件就会自动创建并管理动画过程,无需手动创建 AnimationController 或 Animation 对象。
核心特点:
-
声明式:只需声明最终状态
-
自动管理:自动处理动画时长、曲线和控制器
-
性能优化:内置性能优化
-
易于使用:代码简洁,学习曲线低
二、常用隐式动画组件分类
2.1 容器和布局动画组件
1. AnimatedContainer - 多功能容器动画
最常用的隐式动画组件,可以同时动画化多个属性。
AnimatedContainer(
duration: Duration(seconds: 1), // 动画时长
curve: Curves.easeInOut, // 动画曲线
width: _isExpanded ? 200 : 100, // 宽度变化
height: _isExpanded ? 200 : 100, // 高度变化
color: _isSelected ? Colors.blue : Colors.grey, // 颜色变化
padding: _hasPadding ? EdgeInsets.all(20) : EdgeInsets.zero, // 内边距
margin: EdgeInsets.all(10), // 外边距
alignment: Alignment.center, // 对齐方式
transform: Matrix4.rotationZ(_rotate ? pi/4 : 0), // 变换
decoration: BoxDecoration( // 装饰
borderRadius: BorderRadius.circular(_round ? 20 : 0),
border: Border.all(
color: Colors.black,
width: _hasBorder ? 2 : 0,
),
boxShadow: _hasShadow ? [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
offset: Offset(0, 5),
)
] : [],
),
child: Text('Animated Container'),
)
支持的属性变化:
-
width、height
-
color、decoration
-
padding、margin、alignment
-
constraints
-
transform
-
clipBehavior
2. AnimatedPadding - 内边距动画
专门用于内边距变化的动画。
AnimatedPadding(
duration: Duration(milliseconds: 500),
padding: _isExpanded ?
EdgeInsets.all(30) :
EdgeInsets.symmetric(horizontal: 10, vertical: 5),
curve: Curves.easeOut,
child: Container(
color: Colors.blue,
child: Text('Padding Animation'),
),
)
3. AnimatedAlign - 对齐动画
改变子组件对齐方式的动画。
AnimatedAlign(
duration: Duration(seconds: 1),
alignment: _alignment, // 可以是 Alignment.topLeft、Alignment.center 等
curve: Curves.bounceOut,
child: Container(
width: 100,
height: 100,
color: Colors.green,
child: Center(child: Text('Aligned')),
),
)
// 控制对齐方式
Alignment _alignment = Alignment.topLeft;
void toggleAlignment() {
setState(() {
_alignment = _alignment == Alignment.topLeft
? Alignment.bottomRight
: Alignment.topLeft;
});
}
4. AnimatedPositioned - 定位动画(只能在 Stack 中使用)
用于在 Stack 中改变位置的动画。
Stack(
children: [
// 背景
Container(color: Colors.grey[200]),
AnimatedPositioned(
duration: Duration(seconds: 1),
left: _isRight ? 200 : 0,
top: _isBottom ? 200 : 0,
width: _isLarge ? 150 : 100,
height: _isLarge ? 150 : 100,
child: Container(
color: Colors.red,
child: Center(child: Text('Positioned')),
),
),
],
)
5. AnimatedCrossFade - 交叉淡入淡出动画
在两个子组件之间切换,带有交叉淡入淡出效果。
AnimatedCrossFade(
duration: Duration(milliseconds: 500),
firstChild: Container(
width: 200,
height: 100,
color: Colors.blue,
child: Center(child: Text('First Widget')),
),
secondChild: Container(
width: 200,
height: 150,
color: Colors.green,
child: Center(child: Text('Second Widget')),
),
crossFadeState: _showFirst
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
firstCurve: Curves.easeIn,
secondCurve: Curves.easeOut,
sizeCurve: Curves.easeInOut, // 尺寸变化的曲线
alignment: Alignment.center, // 对齐方式
)
2.2 视觉外观动画组件
6. AnimatedOpacity - 透明度动画
改变透明度的动画。
AnimatedOpacity(
duration: Duration(milliseconds: 300),
opacity: _isVisible ? 1.0 : 0.0, // 0.0 完全透明,1.0 完全不透明
curve: Curves.easeInOut,
// 当 opacity 为 0 时是否占用空间
alwaysIncludeSemantics: false, // 辅助功能相关
child: Container(
width: 200,
height: 200,
color: Colors.blue,
child: Center(
child: Text(
'Fade Animation',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
)
7. AnimatedDefaultTextStyle - 文本样式动画
动态改变文本样式的动画。
AnimatedDefaultTextStyle(
duration: Duration(milliseconds: 500),
style: _isLargeText
? TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.red,
fontStyle: FontStyle.italic,
letterSpacing: 2,
)
: TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black,
),
textAlign: TextAlign.center,
softWrap: true,
overflow: TextOverflow.ellipsis,
maxLines: 2,
child: Text('Text Style Animation'),
)
8. AnimatedPhysicalModel - 物理模型动画
模拟物理效果的动画,如海拔、阴影等。
AnimatedPhysicalModel(
duration: Duration(milliseconds: 500),
curve: Curves.easeInOut,
elevation: _isElevated ? 12 : 2, // 海拔/阴影深度
shape: BoxShape.rectangle, // 形状
borderRadius: BorderRadius.circular(_isRound ? 20 : 8),
color: Colors.blue,
shadowColor: Colors.black54,
child: Container(
width: 150,
height: 150,
child: Center(
child: Text(
'Physical Model',
style: TextStyle(color: Colors.white),
),
),
),
)
9. AnimatedTheme - 主题动画
动态改变主题的动画。
AnimatedTheme(
duration: Duration(seconds: 1),
data: _isDarkTheme
? ThemeData.dark().copyWith(
primaryColor: Colors.blue,
accentColor: Colors.orange,
)
: ThemeData.light().copyWith(
primaryColor: Colors.green,
accentColor: Colors.purple,
),
curve: Curves.easeInOut,
child: Container(
padding: EdgeInsets.all(20),
color: Theme.of(context).primaryColor,
child: Text(
'Theme Animation',
style: TextStyle(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
)
2.3 变换动画组件
10. AnimatedScale - 缩放动画(3.0+)
专门用于缩放的动画组件。
AnimatedScale(
duration: Duration(milliseconds: 500),
scale: _isScaled ? 1.5 : 1.0,
curve: Curves.elasticOut, // 弹性效果
child: Container(
width: 100,
height: 100,
color: Colors.orange,
child: Center(child: Text('Scale')),
),
)
11. AnimatedRotation - 旋转动画(3.0+)
专门用于旋转的动画组件。
AnimatedRotation(
duration: Duration(seconds: 1),
turns: _turns, // 旋转圈数,0.25 = 90度,1 = 360度
curve: Curves.easeInOut,
child: Container(
width: 100,
height: 100,
color: Colors.purple,
child: Center(child: Text('Rotate')),
),
)
double _turns = 0.0;
void rotate() {
setState(() {
_turns += 0.25; // 每次旋转90度
});
}
2.4 列表和网格动画组件
12. AnimatedList - 列表动画
列表项添加/删除时带有动画效果。
final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
List<String> _items = ['Item 1', 'Item 2', 'Item 3'];
AnimatedList(
key: _listKey,
initialItemCount: _items.length,
itemBuilder: (context, index, animation) {
return SizeTransition(
sizeFactor: animation,
child: ListTile(
title: Text(_items[index]),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => _removeItem(index),
),
),
);
},
)
// 添加项目
void _addItem() {
_items.add('Item ${_items.length + 1}');
_listKey.currentState!.insertItem(_items.length - 1);
}
// 删除项目
void _removeItem(int index) {
final removedItem = _items.removeAt(index);
_listKey.currentState!.removeItem(
index,
(context, animation) => SizeTransition(
sizeFactor: animation,
child: ListTile(title: Text(removedItem)),
),
);
}
13. AnimatedGrid - 网格动画(2.10+)
网格项添加/删除时带有动画效果。
final GlobalKey<AnimatedGridState> _gridKey = GlobalKey<AnimatedGridState>();
List<Widget> _gridItems = [
_buildGridItem(Colors.red, '1'),
_buildGridItem(Colors.blue, '2'),
_buildGridItem(Colors.green, '3'),
];
AnimatedGrid(
key: _gridKey,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
initialItemCount: _gridItems.length,
itemBuilder: (context, index, animation) {
return ScaleTransition(
scale: animation,
child: _gridItems[index],
);
},
)
2.5 高级切换动画组件
14. AnimatedSwitcher - 通用切换动画
在子组件之间切换时显示动画。
int _currentIndex = 0;
final List<Widget> _pages = [
Container(key: ValueKey(1), color: Colors.red, child: Center(child: Text('Page 1'))),
Container(key: ValueKey(2), color: Colors.blue, child: Center(child: Text('Page 2'))),
Container(key: ValueKey(3), color: Colors.green, child: Center(child: Text('Page 3'))),
];
AnimatedSwitcher(
duration: Duration(milliseconds: 500),
switchInCurve: Curves.easeIn,
switchOutCurve: Curves.easeOut,
transitionBuilder: (child, animation) {
// 自定义过渡动画
return ScaleTransition(
scale: animation,
child: FadeTransition(
opacity: animation,
child: child,
),
);
},
layoutBuilder: (currentChild, previousChildren) {
return Stack(
alignment: Alignment.center,
children: [
...previousChildren,
if (currentChild != null) currentChild,
],
);
},
child: _pages[_currentIndex],
)
// 切换页面
void nextPage() {
setState(() {
_currentIndex = (_currentIndex + 1) % _pages.length;
});
}
15. AnimatedSize - 尺寸变化动画
自动动画化尺寸变化的组件。
AnimatedSize(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
alignment: Alignment.topCenter, // 尺寸变化时的对齐方式
vsync: this, // 需要混入 SingleTickerProviderStateMixin
child: Container(
width: _isExpanded ? 200 : 100,
height: _isExpanded ? 200 : 100,
color: Colors.amber,
child: Center(child: Text('Size Animation')),
),
)
16. AnimatedModalBarrier - 模态屏障动画
用于模态对话框的动画屏障。
bool _showBarrier = false;
Stack(
children: [
// 主要内容
Center(child: Text('Main Content')),
// 模态屏障
if (_showBarrier)
AnimatedModalBarrier(
dismissible: true,
color: Colors.black.withOpacity(0.5),
duration: Duration(milliseconds: 300),
),
// 模态内容
if (_showBarrier)
Center(
child: Container(
width: 200,
height: 200,
color: Colors.white,
child: Center(child: Text('Modal Content')),
),
),
],
)
三、代码示例
3.1 加载状态动画
bool _isLoading = false;
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedSwitcher(
duration: Duration(milliseconds: 300),
child: _isLoading
? CircularProgressIndicator()
: Icon(Icons.check_circle, color: Colors.green, size: 50),
),
SizedBox(height: 20),
AnimatedOpacity(
duration: Duration(milliseconds: 300),
opacity: _isLoading ? 0.5 : 1,
child: ElevatedButton(
onPressed: _isLoading ? null : () {
setState(() {
_isLoading = true;
});
// 模拟加载过程
Future.delayed(Duration(seconds: 2), () {
setState(() {
_isLoading = false;
});
});
},
child: AnimatedDefaultTextStyle(
duration: Duration(milliseconds: 300),
style: TextStyle(
fontSize: _isLoading ? 14 : 16,
color: _isLoading ? Colors.grey : Colors.white,
),
child: Text(_isLoading ? '加载中...' : '开始加载'),
),
),
),
],
)
更多推荐



所有评论(0)