极简实现酷炫动效:Flutter隐式动画指南第三篇自定义Flutter隐式动画
目录
前言
一、TweenAnimationBuilder
二、使用TweenAnimationBuilder实现的一些动画效果
1.调整透明度的动画
2.稍微复杂点的组合动画
3.数字跳动的动画效果
前言
上两节博客分别介绍了Flutter中的隐式动画的基础知识以及使用隐式动画实现的一些动画效果。当系统提供的隐式动画不能满足我们的需求的时候,我们还可以通过TweenAnimationBuilder 自定义我们的隐式动画。
下面进入正题,我们了解下TweenAnimationBuilder的一些知识。
一、TweenAnimationBuilder
TweenAnimationBuilder 是 Flutter 中用于创建动画的便捷小部件,它提供了一种简单的方法来使用 Tween 定义的值在一段时间内生成平滑的过渡效果。适用于需要根据数值变化进行动画的场景,例如颜色、大小、透明度或位置等过渡效果。
TweenAnimationBuilder 的主要属性包括:
-
tween:用于描述动画的开始和结束值。例如,可以是 Tween<double>(begin: 0, end: 100)
-
duration:动画的持续时间。
-
builder:每一帧调用一次,构建动画效果的 UI,传入当前的动画值。
-
onEnd:动画结束时的回调,可用于触发其他动。
二、使用TweenAnimationBuilder实现的一些动画效果
1.调整透明度的动画
以下代码演示了如何使用 TweenAnimationBuilder 在两种透明度之间创建渐变动画效果:
图1.透明度渐变的动画效果
代码如下:
import 'package:flutter/material.dart';
class TweenAnimationExample extends StatelessWidget {
const TweenAnimationExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: const Text("TweenAnimationBuilder ",style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),),
),
body: Center(
child: TweenAnimationBuilder(
tween: Tween<double>(begin: 0.0, end: 1.0),
duration: const Duration(seconds: 2),
builder: (context, double opacity, child) {
return Opacity(
opacity: opacity,
child: child,
);
},
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
),
);
}
}
- tween 定义了从 0.0 到 1.0 的透明度过渡。
- duration 设置动画持续时间为 2 秒。
- builder 函数在每一帧构建一个带有当前透明度的 Opacity 小部件,从而形成透明度渐变的动画效果。
2.稍微复杂点的组合动画
我们还可以结合隐式动画的渐变、缩放、圆角、旋转等属性实现稍微复杂的动画效果。
例如我们要实现图2所示的动画效果:
图2.复杂的动画效果
代码如下:
import 'package:flutter/material.dart';
import 'dart:math';
class ComplexAnimationExample extends StatefulWidget {
const ComplexAnimationExample({super.key});
@override
State<ComplexAnimationExample> createState() => _ComplexAnimationExampleState();
}
class _ComplexAnimationExampleState extends State<ComplexAnimationExample> {
bool _isAnimated = false;
void _toggleAnimation() {
setState(() {
_isAnimated = !_isAnimated;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: const Text('TweenAnimationBuilder',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),), ),
body: Center(
child: GestureDetector(
onTap: _toggleAnimation,
child: TweenAnimationBuilder(
duration: const Duration(seconds: 2),
tween: Tween<double>(begin: 0, end: _isAnimated ? 2 * pi : 0),
builder: (context, double rotation, child) {
return Transform.rotate(
angle: rotation,
child: TweenAnimationBuilder(
duration: const Duration(seconds: 2),
tween: ColorTween(
begin: Colors.purple, end: _isAnimated ? Colors.orange : Colors.purple),
builder: (context, Color? color, child) {
return TweenAnimationBuilder(
duration: const Duration(seconds: 2),
tween: BorderRadiusTween(
begin: BorderRadius.circular(10),
end: BorderRadius.circular(_isAnimated ? 75 : 10)),
builder: (context, BorderRadius? borderRadius, child) {
return TweenAnimationBuilder(
duration: const Duration(seconds: 2),
tween: Tween<double>(
begin: 100, end: _isAnimated ? 200 : 100),
builder: (context, double size, child) {
return Container(
width: size,
height: size,
decoration: BoxDecoration(
color: color,
borderRadius: borderRadius,
),
child: child,
);
},
child: const Center(
child: Text(
'点击看动画!',
style: TextStyle(
fontSize: 14, color: Colors.white),
),
),
);
},
);
},
),
);
},
),
),
),
);
}
}
在我们的例子中:
1. 旋转:最外层的 TweenAnimationBuilder 使用 Tween<double> 定义旋转角度的动画,从 0 到 2π,即旋转一整圈。
2. 颜色渐变:在旋转的基础上,嵌套了一个 TweenAnimationBuilder,使用 ColorTween 从紫色渐变到橙色。
3. 边框圆角:进一步嵌套了一个 BorderRadiusTween,实现容器边框从圆角半径 10 变化到 75。
4. 尺寸变化:最内层的 TweenAnimationBuilder 使用 Tween<double> 控制容器大小在 100 到 200 之间平滑过渡。
5. 点击切换动画:通过 GestureDetector 包裹,点击容器触发 _toggleAnimation() 方法,使 _isAnimated 状态切换并重建 Widget,从而实现动画的来回切换。
3.数字跳动的动画效果
我们在使用一些支付app的时候,经常会看到图3所示的动画效果。
我们看看如何使用TweenAnimationBuilder实现数字的渐变动画。
大致的思路如下:使用 TweenAnimationBuilder 实现一个数字从 1000 到 2000 的渐变动画。TweenAnimationBuilder 能够逐步生成中间值,从而呈现数字的平滑渐变效果。下面是一个完整的示例代码,通过 Tween<int> 来定义数字范围并逐步更新显示的数值。
图3.数字渐变动画
代码如下:
import 'package:flutter/material.dart';
class NumberTransitionExample extends StatefulWidget {
const NumberTransitionExample({super.key});
@override
State<NumberTransitionExample> createState() => _NumberTransitionExampleState();
}
class _NumberTransitionExampleState extends State<NumberTransitionExample> {
bool _isAnimating = false;
void _toggleAnimation() {
setState(() {
_isAnimating = !_isAnimating;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.purple,
title: const Text('TweenAnimationBuilder',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 16),),
),
body: Center(
child: TweenAnimationBuilder(
tween: IntTween(begin: 1000, end: _isAnimating ? 2000 : 1000),
duration: const Duration(seconds: 3),
onEnd: () => debugPrint("Animation Complete"),
builder: (context, int value, child) {
return Text(
'$value',
style: const TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: _toggleAnimation,
child: const Icon(Icons.play_arrow),
),
);
}
}
在上面的例子中:Tween<int>:使用 IntTween 将动画的整数起点设为 1000,终点为 2000。点击按钮后,起点和终点之间的值会逐步更新。
点击“播放”按钮后,屏幕上数字会从 1000 平滑过渡到 2000,直到动画完成。