main.dart:
import 'package:flutter/material.dart';
import 'mask.dart';
void main(){
runApp(MyApp());
}
//通过BorderRadiusTween和Tween共用一个AnimationController,即叠加多个动画,实现类似遮罩的效果,Tween动画负责宽高,BorderRadiusTween负责边框圆角动画
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: MaterialApp(
title: 'Flutter边框补间动画BorderRadiusTween实现遮罩动画',
theme: ThemeData(
primarySwatch: Colors.blue
),
debugShowCheckedModeBanner: false,
home: AnimateDemo(),
),
);
}
}
class AnimateDemo extends StatelessWidget{
@override
Widget build(BuildContext context) {
List<Widget> list = [
MaskAnimation()
];
return Scaffold(
appBar: AppBar(
title: Text('动画示例'),
),
body: ListView(
children: list.map((widget){
return ListTile(
title: Text(widget.toString()),
onTap: (){
Navigator.of(context).push(MaterialPageRoute(builder: (context)=>widget));
},
);
}).toList(),
),
);
}
}
mask.dart:
import 'package:flutter/material.dart';
class MaskAnimation extends StatefulWidget{
MaskAnimation({Key key}) : super(key:key);
_MaskAnimationState createState() => _MaskAnimationState();
}
//混入 SingleTickerProviderStateMixin 是为了在不显示当前页面时,动画停止,节约资源
class _MaskAnimationState extends State<MaskAnimation> with SingleTickerProviderStateMixin{
AnimationController _controller;
Animation<double> transitionTween;
Animation<BorderRadius> borderRadius;
@override
void initState() {
super.initState();
_controller = AnimationController(duration:Duration(seconds: 10), vsync: this)
..addStatusListener((status) {
if(status == AnimationStatus.completed){
Navigator.pop(context);
}
});
transitionTween = Tween<double>(begin: 50, end: 200).animate(
//非线性动画
CurvedAnimation(
parent: _controller,
curve: Curves.ease
)
);
//边框弧度补间动画
borderRadius = BorderRadiusTween(begin: BorderRadius.circular(75.0), end: BorderRadius.circular(0.0)).animate(
//非线性动画
CurvedAnimation(
parent: _controller,
curve: Curves.ease
)
);
_controller.forward();
}
//销毁动画
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context,child){
return Scaffold(
appBar: AppBar(
title: Text('遮罩动画'),
),
body: Center(
child: Stack(
children: [
Center(
child: Container(
width: 200.0,
height: 200.0,
color: Colors.black12,
),
),
Center(
child: Container(
alignment: Alignment.bottomCenter,
width: transitionTween.value,
height: transitionTween.value,
decoration: BoxDecoration(
color: Colors.black12,
borderRadius: borderRadius.value
),
color: Colors.black12,
),
),
],
),
),
);
}
);
}
}
