闪屏动画是什么?
闪屏,实际上有两个作用。
宣传。通过Logo、广告等形式,在启动时,展示要宣传的广告等内容。
后台初始化。借助这个时间做一些后台操作,初始化一些SDK或者代码。
Flutter Dojo的闪屏动画,参考了著名大厂——P站的App闪屏,相信大家应该都不陌生。
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
动画其实比较简单,只是一个从两边向中间靠拢的动画。
一般来说,Flutter的动画创作,有下面几个步骤。
创建静态布局
创建Tween,标记动画的起始值
给静态代码添加AnimatedBuilder,驱动动画
静态布局
这个布局没有什么太大难度,这个效果其实有很多实现方案,比如Center-Row的方式,让【Flutter】Text和【Dojo】Text在Row中居中即可。或者可以用Stack-Positioned的方式,通过left、right来定位。
相比来说,Center-Row的方式会比较直观,所以我这里准备使用Stack-Positioned的方式来进行演示。
不管使用哪种方案,需要注意的一点是,【Flutter】Text和【Dojo】Text是整体居中的,并不是分别居中,因为【Flutter】Text比【Dojo】Text要长,所以沿屏幕中线居中会很不协调。
布局之外,需要稍微提下【Dojo】Text的实现,实际上就是通过BoxDecoration来实现的,代码如下所示。
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Color.fromARGB(255, 253, 152, 39),
),
定义动画
这里的动画分为两部分,左边和右边,如果使用Center-Row的方式,由于两个Text并不在屏幕中线对齐,所以实际上是有个offset的,然后再通过Transform.translate来进行偏移。另一种方式,Stack-Positioned实际上也是如此,但是可以通过Positioned中的left和right来进行动画。
所以首先一步,需要获取【Flutter】Text和【Dojo】Text的宽度差,这里又有多种方式来获取一个Widget的Size了。
LayoutBuilder。由于需要提前创建动画,所以这个方案不是很好。
TextPainter。对于文字,可以使用TextPainter来进行文本的测量。
Key。通过Key来获取RenderBox,从而获取Widget的Size。
Key的方式比较简单,所以这里我准备用TextPainter的方式来演示。下面这个函数就演示了如何获取一个特定TextStyle下Text的计算宽度。
double getTextWidth(String text) {
final textPainter = TextPainter(
text: TextSpan(
text: text,
style: TextStyle(
fontSize: 60,
fontWeight: FontWeight.w600,
),
),
textDirection: TextDirection.ltr,
);
textPainter.layout(minWidth: 0, maxWidth: double.infinity);
return textPainter.width;
}
经过简单的计算,【Flutter】Text和【Dojo】Text偏移的值实际上就是两个文本的宽度差的一半。
watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=
由于前面使用的是Stack-Positioned的方式进行的布局,所以动画也需要根据静态布局来定义。
先看【Flutter】Text的动画,它从屏幕左边作用到中间带偏移的地方,所以其动画值的范围是:
begin: screenWidth, end: screenWidth / 2 - offset
相应的,【Dojo】Text的动画,也类似:
begin: screenWidth, end: screenWidth / 2 + offset
动画管理
在确定的动画值的范围之后,实际上Tween就已经确定了,这里介绍一个动画管理的技巧,通过一个类来封装Widget所需要的不同的Tween,这样可以将动画的逻辑和Widget进行解耦,代码如下所示。
import 'package:flutter/material.dart';
class SplashAnimManager {
final AnimationController controller;
final Animation<double> animLeft;
final Animation<double> animRight;
final double screenWidth;
final double offset;
SplashAnimManager(this.controller, this.screenWidth, this.offset)
: animLeft = Tween(begin: screenWidth, end: screenWidth / 2 - offset).animate(
CurvedAnimation(
parent: controller,
curve: Curves.easeIn,
),
),
animRight = Tween(begin: screenWidth, end: screenWidth / 2 + offset).animate(
CurvedAnimation(
parent: controller,
curve: Curves.easeIn,
),
);
}
这里仅仅是为了演示这种动画管理的思想,才将仅仅两个动画写在了管理类中。
Copyright © 广州京杭网络科技有限公司 2005-2024 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有