这是我参与更文挑战的第5天,活动详情查看: 更文挑战
本文已参与 周末学习计划,点击查看详情
前言
上一篇我们聊了 Flutter 中最常用的 Widget Container
对应的动画组件 AnimatedContainer
,它的很多属性都可以在值发生变化的时候以动画的方式转换。
如果我们只想对单个属性比如 padding
来设置的话,嵌套一个 AnimatedContainer
就显的有些**笨重,**还有在 Stack
中我们要使用绝对定位时也是无法优雅实现的。
这一篇我们就来聊聊 Flutter 中的几个「单属性动画组件」。
AnimatedPadding (动画边距)
这个 Widget 与 AnimatedContainer
中的 padding
属性类似,只需要我们设置一个 duration
和 padding
即可,单独使用嵌套在我们自定义的组件上是非常方便的。
/// 属性
var height = 100.0;
Duration duration = Duration(milliseconds: 300);
var padding = 0.0;
// 设置
GestureDetector(
onTap: () {
// 点击改变边距
this.padding = padding == 0 ? 30 : 0;
setState(() {});
},
child: AnimatedPadding(
duration: duration,
curve: Curves.easeIn,
// 设置边距
padding: EdgeInsets.all(padding),
child: DescContainer(
height: height,
width: width,
color: Colors.blue,
text: 'AnimatedPadding',
),
),
)
复制代码
自定义通用 DescContainer
这个是我们抽离的通用描述容器组件,为了之后我们复用,项目中也建议大家把通用的 Widget 抽离成单独的组件来使用,通常需要扩展时增加属性即可。
/// 通用描述容器
class DescContainer extends StatelessWidget {
const DescContainer({
Key? key,
required this.color,
required this.height,
required this.width,
required this.text,
}) : super(key: key);
// 背景颜色
final Color color;
// 宽度
final double width;
// 高度
final double height;
// 文字
final String text;
@override
Widget build(BuildContext context) {
return Container(
color: color,
height: height,
width: width,
alignment: Alignment.center,
child: Text(
text,
style: TextStyle(
color: Colors.white,
),
),
);
}
}
复制代码
AnimatedAlign (动画对齐)
上一篇中我们在 AnimatedContainer
中通过设置 alignment
属性来改变 Text 的对齐,这里 Flutter 为我们单独写了一个方便我们使用。
/// 属性
var alignment = Alignment.center;
GestureDetector(
onTap: () {
var x = Random.secure().nextInt(3);
var y = Random.secure().nextInt(3);
// Alignment 设置对齐方式是由 [-1、0、1] 设置 x 和 y 来组成的
this.alignment = Alignment(x - 1, y - 1);
setState(() {});
},
// 背景
child: Container(
height: 200,
color: Colors.grey[350],
child: AnimatedAlign(
// 设置对齐方式
alignment: alignment,
duration: duration,
child: DescContainer(
height: 60,
width: 180,
color: Colors.amber,
text: 'AnimatedAlign',
),
),
),
)
复制代码
Alignment 对齐方式(一起看源码)
这里我们扩展一下,看看源码中 Alignment
是怎么实现的。
// Alignment 类继承自 AlignmentGeometry
class Alignment extends AlignmentGeometry {
const Alignment(this.x, this.y)
: assert(x != null),
assert(y != null);
final double x;
final double y;
static const Alignment topLeft = Alignment(-1.0, -1.0);
...
static const Alignment center = Alignment(0.0, 0.0);
...
static const Alignment bottomRight = Alignment(1.0, 1.0);
...
}
复制代码
这里可以看到 Alignment
就是由 x、y 两个属性组成的类,其中 x 和 y 的值是 [-1,0,1] 分别表示如下:
- x:[-1,0,1] :[左,中,右]
- y:[-1,0,1] :[上,中,下]
也可以看到 topLeft、center、bottomRight
等这些我们经常使用的常量是由 x、y 的 [-1,0,1] 组成
AnimatedPositioned(定位动画)
在项目中也经常会使用到 Stack
,然后通过给 子 Widget
嵌套一个 Positioned
来实现子组件的定位布局,如果要加上动画我们使 AnimatedPositioned
即可,来看看效果。
/// 这里我们就不贴全部代码了
/// 点击改变左上右下距离
onTap: () {
this.top = top == 0 ? 20 : 0;
this.left = left == 0 ? 30 : 0;
this.right = right == 0 ? 40 : 0;
this.bottom = bottom == 0 ? 80 : 0;
setState(() {});
}
Stack(
fit: StackFit.expand,
children: [
AnimatedPositioned(
// 设置动画时长
duration: duration,
// 设置动画曲线
curve: Curves.decelerate,
// 设置定位左上
top: top,
left: left,
child: DescContainer(
height: 60,
width: 180,
color: Colors.cyan,
text: 'AnimatedPositioned',
),
),
AnimatedPositioned(
duration: duration,
curve: Curves.decelerate,
// 设置定位右下
right: right,
bottom: bottom,
child: DescContainer(
height: 60,
width: 180,
color: Colors.amber,
text: 'AnimatedPositioned',
),
),
],
)
复制代码
AnimatedOpacity(动画不透明)
如果你想要透明度改变时也有一个动画效果,那么可以使用这个 Widget,只需要设置 opacity
不透明度即可,一般在过渡动画时使用效果非常好。
GestureDetector(
onTap: () {
// 点击切换改变透明度,
this.opacity = opacity == 1 ? 0.5 : 1;
setState(() {});
},
child: AnimatedOpacity(
// 设置透明度
opacity: opacity,
// 设置动画时长
duration: duration,
// 设置动画曲线
curve: Curves.easeOut,
child: DescContainer(
height: 60,
width: 300,
color: Colors.purple,
text:
'AnimatedOpacity opacity:${opacity.toStringAsFixed(2)}',
),
),
)
复制代码
范围
- 范围是 0.0~1.0
- 1:完全不透明
- 0:完全透明
源码仓库
基于 Flutter ? 最新版本
参考链接
- AnimatedPadding (Flutter Widget of the Week)
- Flutter-AnimatedPadding
- Flutter-AnimatedAlign
- AnimatedPositioned (Flutter Widget of the Week)
- Flutter-AnimatedPositioned
- AnimatedOpacity (Flutter Widget of the Week)
- Flutter-AnimatedOpacity
关注专栏
- 此文章已收录到下面? 的专栏,可以直接关注
- 更多文章继续阅读|系列文章持续更新
? 欢迎点赞➕收藏➕关注,有任何问题随时在下面?评论,我会第一时间回复哦