AnimatedCrossFade
在两个不同的子控件及其大小之间淡入淡出动画,因此AnimatedCrossFade
需要设置2个子控件、动画时间和显示第几个子控件。
- 构造函数
const AnimatedCrossFade({
super.key,
required this.firstChild,//第一个子控件
required this.secondChild,//第二个子控件
this.firstCurve = Curves.linear,//第一个子控件动画曲线
this.secondCurve = Curves.linear,//第二个子控件动画曲线
this.sizeCurve = Curves.linear,//组件动画曲线
this.alignment = Alignment.topCenter,//对齐位置
required this.crossFadeState,//显示的孩子将淡入,而另一个将淡出
required this.duration,//动画时间
this.reverseDuration,//方向动画时间
this.layoutBuilder = defaultLayoutBuilder,//解决过渡抖动问题
this.excludeBottomFocus = true,
})
layoutBuilder
当我们从一个状态转到另一个状态时,会有一个奇怪的跳跃,这时会用到layoutbuilder
。layoutbuilder
将返回一个Stack
带有两个Positioned
小部件的小部件。第一个Positioned
小部件将获取bottomChild
小部件,第二个Positioned
小部件将获取topChild
小部件。
例子:
import 'package:flutter/material.dart';
class AnimatedCrossFadePage extends StatefulWidget {
const AnimatedCrossFadePage({Key? key}) : super(key: key);
@override
State<AnimatedCrossFadePage> createState() => _AnimatedCrossFadePageState();
}
class _AnimatedCrossFadePageState extends State<AnimatedCrossFadePage> {
bool showPost = false;//渲染
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('AnimatedCrossFade'),),
body: Center(
child: AnimatedCrossFade(
firstChild: GestureDetector(
onTap: (){
setState(() {
showPost = true;
});
},
child: Container(
width: 300,
height: 400,
color: Colors.black,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('第一个widget',style: TextStyle(fontSize: 30,color: Colors.white),),
const SizedBox(height: 200,),
OutlinedButton(
onPressed: (){
setState(() {
showPost = true;
});
},
child: const Text('点击淡出'),
)
],
),
),
),
secondChild: GestureDetector(
onTap: (){
setState(() {
showPost = false;
});
},
child: Container(
width: 400,
height: 500,
color: Colors.blueGrey,
child: Image.asset('images/liu.webp'),
),
),
duration: const Duration(seconds: 1),
crossFadeState: !showPost ? CrossFadeState.showFirst: CrossFadeState.showSecond,
layoutBuilder: (topChild,topChildKey,bottomChild, bottomChildKey){
return Stack(
//必须添加Alignment.center和clipBehaviourClip.none,不然达不到预期效果
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
Positioned(
key: bottomChildKey,
top: 0.0,
child: bottomChild,
),
Positioned(
key: topChildKey,
child: topChild,
),
],
);
},
),
),
);
}
}
效果: