Flutter中FadeTransition+Hero动画快速跳转图标冻结问题求助
Flutter Hero组件结合FadeTransition快速跳转时图标冻结异常问题
在Flutter开发场景下,当结合FadeTransition转场动画与Hero组件进行页面跳转时,若在Hero组件完成淡出前快速触发再次跳转,会出现图标冻结在屏幕上的异常。以下是可复现该Bug的完整代码示例,恳请各位开发者提供解决方案。
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class AppRoutes { static MaterialPageRoute? getRoute(RouteSettings settings) { switch (settings.name) { case "/": return MainRoute( MyHomePage(), settings: settings, ); } } } class MainRoute<T> extends MaterialPageRoute<T> { MainRoute( Widget widget, { RouteSettings? settings, }) : super(builder: (_) => widget, settings: settings); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', onGenerateRoute: (RouteSettings settings) => AppRoutes.getRoute( settings, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( 'You have pushed the button this many times:', ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => TestScreen(), ), ); }, child: const Icon(Icons.route), ), ); } } class TestScreen extends StatefulWidget { const TestScreen({ super.key, this.isSuccess = false, }); final bool isSuccess; @override State<TestScreen> createState() => _TestScreenState(); } class _TestScreenState extends State<TestScreen> { @override void initState() { super.initState(); _redirectToDetailPage(); } void _redirectToDetailPage() async { Future.delayed(const Duration(seconds: 2), () { Navigator.push( context, PageRouteBuilder( maintainState: false, opaque: true, pageBuilder: (_, Animation<double> start, Animation<double> end) { return TestUnsuccess( test: end, ); }, transitionsBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition( opacity: animation, child: child, ); }, transitionDuration: Duration(milliseconds: 2000), ), ); }); } @override Widget build(BuildContext context) { return Scaffold( body: PopScope( canPop: false, child: SafeArea( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Hero( tag: 'payment_icon', child: Icon( Icons.abc, size: 40, ), ), SizedBox( height: 32.0, ), ], ), ), ), ), ); } } class TestUnsuccess extends StatefulWidget { final Animation<double> test; TestUnsuccess({ required this.test, }); @override TestUnsuccessState createState() => TestUnsuccessState(); } class TestUnsuccessState extends State<TestUnsuccess> { @override void initState() { super.initState(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: PopScope( canPop: false, child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Hero( tag: 'payment_icon', child: Icon( Icons.abc, size: 40, ), ), SizedBox( height: 16.0, ), ElevatedButton( child: Icon( Icons.home_filled, ), onPressed: () { Navigator.of(context).pushNamedAndRemoveUntil( "/", ModalRoute.withName('/'), ); Navigator.of(context).push( MaterialPageRoute( builder: (context) => TestAnother(), ), ); }, ), ], ), ), ), ); } } class TestAnother extends StatefulWidget { @override State<TestAnother> createState() => _TestAnotherState(); } class _TestAnotherState extends State<TestAnother> { @override Widget build(BuildContext context) { return Scaffold( body: Container( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( 'You have pushed the button this many times:', ), ], ), ), ), ); } }

内容的提问来源于stack exchange,提问作者chris
相关产品推荐
相关产品推荐

