引言
本文将详细介绍以下 6 个核心动画组件 和一个常用的 UI 组件:
AnimatedOpacity:透明度动画
AnimatedPhysicalModel:物理模型(阴影、圆角等)动画
AnimatedPositioned:用于 Stack 中元素的定位动画
AnimatedSize:尺寸自适应动画
AnimatedWidget:自定义动画构建基类
AppBar:应用顶部导航栏
1. AnimatedOpacity:透明度动画组件
用途:
AnimatedOpacity 用于在 opacity 值变化时自动执行淡入淡出动画。
示例代码:
class AnimatedOpacityDemo extends StatefulWidget {
@override
_AnimatedOpacityDemoState createState() => _AnimatedOpacityDemoState();
}
class _AnimatedOpacityDemoState extends State<AnimatedOpacityDemo> {
double _opacity = 1.0;
void _toggleOpacity() {
setState(() {
_opacity = _opacity == 1.0 ? 0.2 : 1.0;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("AnimatedOpacity")),
body: Center(
child: AnimatedOpacity(
opacity: _opacity,
duration: Duration(seconds: 1),
curve: Curves.easeInOut,
child: Container(
width: 200,
height: 200,
color: Colors.blue,
alignment: Alignment.center,
child: Text(
"Fade In/Out",
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _toggleOpacity,
child: Icon(Icons.visibility),
),
);
}
}
参数说明:
opacity 透明度值(0.0 完全透明,1.0 完全不透明)
duration 动画持续时间
curve 动画曲线(如 Curves.ease, Curves.bounceOut)
使用场景:
- 图片加载占位符淡入
- 按钮禁用状态视觉提示
- 消息提示自动隐藏
AnimatedPhysicalModel:物理外观动画组件
用途:
AnimatedPhysicalModel 可以动画化地改变组件的物理外观,如阴影、圆角、边框、海拔(elevation)等。
示例代码:
class AnimatedPhysicalModelDemo extends StatefulWidget {
@override
_AnimatedPhysicalModelDemoState createState() =>
_AnimatedPhysicalModelDemoState();
}
class _AnimatedPhysicalModelDemoState extends State<AnimatedPhysicalModelDemo> {
bool _elevated = false;
void _toggleElevation() {
setState(() {
_elevated = !_elevated;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("AnimatedPhysicalModel")),
body: Center(
child: AnimatedPhysicalModel(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
elevation: _elevated ? 20 : 0,
color: Colors.white,
shadowColor: Colors.black,
borderRadius: BorderRadius.circular(_elevated ? 20 : 0),
child: Container(
width: 200,
height: 200,
color: Colors.purple,
alignment: Alignment.center,
child: Text(
"Elevated",
style: TextStyle(color: Colors.white),
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _toggleElevation,
child: Icon(Icons.change_circle),
),
);
}
}
参数说明:
elevation 海拔高度(影响阴影)
color / shadowColor 背景色和阴影颜色
borderRadius 圆角半径
shape 形状(矩形、圆形)
使用场景:
- 卡片点击高亮效果
- 明暗模式切换时的 UI 变化
- 悬浮按钮动态提升
3. AnimatedPositioned:Stack 中的定位动画
用途:
AnimatedPositioned 是 Positioned 的动画版本,用于在 Stack 中对子组件进行带动画的定位。
示例代码:
class AnimatedPositionedDemo extends StatefulWidget {
@override
_AnimatedPositionedDemoState createState() => _AnimatedPositionedDemoState();
}
class _AnimatedPositionedDemoState extends State<AnimatedPositionedDemo> {
bool _move = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("AnimatedPositioned")),
body: Stack(
children: [
AnimatedPositioned(
duration: Duration(seconds: 1),
curve: Curves.elasticOut,
top: _move ? 300 : 100,
left: _move ? 200 : 50,
child: Container(
width: 100,
height: 100,
color: Colors.orange,
alignment: Alignment.center,
child: Text("Move", style: TextStyle(color: Colors.white)),
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_move = !_move;
});
},
child: Icon(Icons.directions_run),
),
);
}
}
参数说明:
top / left / right / bottom 相对位置
width / height 尺寸(也可动画)
duration 动画持续时间
curve 动画曲线
使用场景:
- 拖拽元素回弹动画
- 引导页元素移动
- 游戏角色移动动画
4. AnimatedSize:自动尺寸动画
用途:
AnimatedSize 会在其子组件尺寸发生变化时,自动执行尺寸过渡动画。
示例代码:
class AnimatedSizeDemo extends StatefulWidget {
@override
_AnimatedSizeDemoState createState() => _AnimatedSizeDemoState();
}
class _AnimatedSizeDemoState extends State<AnimatedSizeDemo>
with TickerProviderStateMixin {
bool _expanded = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("AnimatedSize")),
body: Center(
child: AnimatedSize(
duration: Duration(milliseconds: 300),
curve: Curves.fastOutSlowIn,
child: Container(
width: _expanded ? 300 : 100,
height: _expanded ? 300 : 100,
color: Colors.teal,
padding: EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("Tap to Expand", style: TextStyle(color: Colors.white)),
if (_expanded)
Text("Expanded Content", style: TextStyle(color: Colors.white)),
],
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_expanded = !_expanded;
});
},
child: Icon(Icons.expand),
),
);
}
}
参数说明:
duration 动画持续时间
curve 动画曲线
alignment 对齐方式
child 子组件(尺寸变化会触发动画)
使用场景:
- 折叠/展开面板
- 动态内容区域尺寸变化
- 加载更多内容时的平滑扩展
5. AnimatedWidget:自定义动画组件基类
用途:
AnimatedWidget 是一个抽象类,用于创建依赖于 Listenable(通常是 Animation)的可重用动画组件。
示例代码:自定义旋转图标
class RotatingIcon extends AnimatedWidget {
final IconData icon;
final double size;
const RotatingIcon({
Key? key,
required Animation<double> animation,
this.icon = Icons.refresh,
this.size = 24,
}) : super(key: key, listenable: animation);
@override
Widget build(BuildContext context) {
final Animation<double> animation = listenable as Animation<double>;
return Transform.rotate(
angle: animation.value * 2 * pi,
child: Icon(icon, size: size),
);
}
}
// 使用示例
class AnimatedWidgetDemo extends StatefulWidget {
@override
_AnimatedWidgetDemoState createState() => _AnimatedWidgetDemoState();
}
class _AnimatedWidgetDemoState extends State<AnimatedWidgetDemo>
with TickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(seconds: 2),
vsync: this,
)..repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("AnimatedWidget")),
body: Center(
child: RotatingIcon(
animation: _controller,
icon: Icons.sync,
size: 50,
),
),
);
}
}
优势:
- 将动画逻辑封装成可复用组件
- 自动监听动画变化并重建 UI
- 提高代码复用性和可维护性
使用场景:
- 自定义加载动画
- 可复用的动效图标
- 复杂动画组件封装
6. AppBar:应用顶部导航栏
用途:
AppBar 是 Material Design 风格的应用顶部导航栏,通常作为 Scaffold 的一部分使用。
示例代码:
class AppBarDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("AppBar 示例"),
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {
Scaffold.of(context).openDrawer();
},
),
actions: [
IconButton(
icon: Icon(Icons.search),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.more_vert),
onPressed: () {},
),
],
backgroundColor: Colors.blue,
elevation: 4,
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size.fromHeight(48),
child: Container(
height: 48,
alignment: Alignment.center,
child: Text("标签页"),
),
),
),
body: Center(child: Text("页面内容")),
);
}
}
核心参数说明:
title 标题文本或组件
leading 左侧按钮(如菜单、返回)
actions 右侧操作按钮列表
backgroundColor 背景色
elevation 阴影高度
centerTitle 标题是否居中
bottom 底部附加组件(如 TabBar)
flexibleSpace 背景空间(用于背景图片等)
使用场景:
- 页面标题展示
- 导航控制(返回、菜单)
- 搜索、设置等操作入口
- Tab 切换导航
最佳实践建议
- 使用 AnimatedOpacity 实现淡入淡出效果,简单高效。
- 使用 AnimatedPhysicalModel 创建具有物理反馈的 UI 元素。
- 使用 AnimatedPositioned 实现 Stack 内元素的平滑移动。
- 使用 AnimatedSize 实现内容区域的平滑展开/收起。
- 使用 AnimatedWidget 封装复杂或可复用的动画逻辑。
- 使用 AppBar 标准化应用导航,提升用户体验一致性。