接触flutter开发已有几年时间,前期主要是自己仿写项目,后面在新公司开始用flutter正式进入开发了,但是flutter主要还是写业务页面,动画相关的写相对较少,最近公司设计老师提了一些动画需求,有幸可以亲自来实现,感受到了flutter写动画强大,赞👍🏻!!!
- 实现Text文本内容变化时渐变动画
先看效果:
再看代码:
/// 常量
/// 页面切换动画时间,单位毫秒
const int pageViewAnimationDuration = 350;
class DemoWidget extends StatefulWidget {
/// 是否显示年龄标题
final bool showAge;
const DemoWidget({
Key? key,
required this.showAge,
}) : super(
key: key,
);
@override
State<StatefulWidget> createState() => _DemoWidgetState();
}
class _DemoWidgetState extends State<DemoWidget> with TickerProviderStateMixin {
late AnimationController _text_1_controller;
late Animation<double> _text_1_animation;
late AnimationController _text_2_Controller;
late Animation<double> _text_2_animation;
/// 是否是第一次进入显示,第一次进入不显示渐变动画
bool isFirstShow = true;
@override
void initState() {
super.initState();
_text_1_controller = AnimationController(
duration: const Duration(milliseconds: pageViewAnimationDuration),
vsync: this,
);
_text_1_animation =
Tween<double>(begin: 0, end: 1).animate(_text_1_controller);
_text_2_Controller = AnimationController(
duration: const Duration(milliseconds: pageViewAnimationDuration),
vsync: this,
);
_text_2_animation =
Tween<double>(begin: 0, end: 1).animate(_text_2_Controller);
}
@override
void dispose() {
_text_1_controller.dispose();
_text_1_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
/// 执行动画,这里需要将两个text的动画相反执行,就可满足效果
if (widget.showAge == true) {
_text_1_controller.forward();
_text_2_Controller.reverse();
} else {
_text_1_controller.reverse();
_text_2_Controller.forward();
}
List<Widget> children = [];
children.add(
SizedBox(
height: 24,
),
);
/// 标题和logo的间距
children.add(
SizedBox(
height: 16,
),
);
if (isFirstShow) {
/// 第一次显示时,不显示文字渐变动画
isFirstShow = false;
children.add(
_buildFadeTransitionWidget(
animation: null,
text: "文字1 标题",
fontSize: 24,
fontWeight: FontWeight.w600,
fontColor: ConstantColor.brandGrey,
),
);
children.add(
SizedBox(
height: 4,
),
);
children.add(
_buildFadeTransitionWidget(
animation: null,
text: "文字1 描述",
fontSize: 16,
fontWeight: FontWeight.normal,
fontColor: ConstantColor.brandGrey,
),
);
} else {
children.add(
Stack(
children: [
_buildFadeTransitionWidget(
animation: _text_1_animation,
text: "文字2 标题",
fontSize: 24,
fontWeight: FontWeight.w600,
fontColor: ConstantColor.brandGrey,
),
_buildFadeTransitionWidget(
animation: _text_2_animation,
text: "文字2 标题",
fontSize: 24,
fontWeight: FontWeight.w600,
fontColor: ConstantColor.brandGrey,
),
],
),
);
children.add(
SizedBox(
height: 4,
),
);
children.add(
Stack(
children: [
_buildFadeTransitionWidget(
animation: _text_1_animation,
text: "文字1 - 描述",
fontSize: 16,
fontWeight: FontWeight.normal,
fontColor: ConstantColor.brandGrey,
),
_buildFadeTransitionWidget(
animation: _text_2_animation,
text: "文字2 - 描述",
fontSize: 16,
fontWeight: FontWeight.normal,
fontColor: ConstantColor.brandGrey,
),
],
),
);
}
return Container(
color: Colors.white,
width: 311,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Column(
children: children,
),
),
],
),
);
}
_buildFadeTransitionWidget({
Animation<double>? animation,
required String text,
required double fontSize,
required FontWeight fontWeight,
required Color fontColor,
}) {
if (animation != null) {
return Center(
child: FadeTransition(
opacity: animation,
child: Text(
text,
overflow: TextOverflow.ellipsis,
maxLines: 1,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: fontSize,
fontWeight: fontWeight,
color: fontColor,
),
),
),
);
}
return Center(
child: Text(
text,
overflow: TextOverflow.ellipsis,
maxLines: 1,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: fontSize,
fontWeight: fontWeight,
color: fontColor,
),
),
);
}
}
实现思路:
从动画效果上来,是之前的文字渐变消失,之后的文字渐变出现,这两个动画是同时执行的,那么我当时的思路是用两层Text组件叠放在一起,用Stack组件进行包裹,然后上下两层Text组件执行的动画相反即可满足。
后续还有些动画,持续更新~