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, ), ), ], ), ), ); } ); } }