Flutter AnimatedSplashScreen显示白屏问题求助
问题:使用AnimatedSplashScreen组件出现白屏
应用运行时AnimatedSplashScreen显示白屏,截图如下:
SplashScreen类代码:
class SplashScreen extends StatelessWidget { const SplashScreen({super.key}); @override Widget build(BuildContext context) { final user = AuthService().currentUser; String nextScreen = user != null ? RoutesEnum.homePage : RoutesEnum.loginPage; return AnimatedSplashScreen( duration: 1500, splash: Icons.home, nextScreen: LoginPage(), nextRoute: nextScreen, splashTransition: SplashTransition.rotationTransition, );}}
main.dart代码:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(MaterialApp( debugShowCheckedModeBanner: false, theme: mainTheme, home: const SplashScreen(), routes: { //RoutesEnum.splashScreen: (context) => const SplashScreen(), RoutesEnum.loginPage: (context) => LoginPage(), RoutesEnum.signUpPage: (context) => SignUpPage(), RoutesEnum.homePage: (context) => HomePage(), }, )); }
补充:LoginPage代码
class LoginPage extends StatefulWidget { @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { final authService = AuthService(); final emailcon = TextEditingController(); final passwordcon = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( resizeToAvoidBottomInset: false, body: Stack( children: [ Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( "assets/images/Logo_ohne_Hintergrund.png", color: Colors.white.withOpacity(0.75), colorBlendMode: BlendMode.modulate, ), addVerticalSpace(60), addFormEmailPassword(emailcon, passwordcon), addVerticalSpace(20), RoundButton( title: "Login", tapfun: () => { if (emailcon.text.toString().isEmpty || passwordcon.text.toString().isEmpty) { toastmessage("Eingaben prüfen"), } else { authService .signInWithEmailAndPassword( email: emailcon.text.toString(), password: passwordcon.text.toString(), ) .then( (value) => { if (value) { Navigator.pushReplacementNamed( context, RoutesEnum.homePage, ), } }, ), } }, ), addVerticalSpace(20), const Text("- OR -"), addVerticalSpace(20), GoogleAuthButton( style: AuthButtonStyle( buttonType: AuthButtonType.icon, buttonColor: Theme.of(context).backgroundColor, borderRadius: 25, ), onPressed: () => { authService.signInWithGoogle().then( (value) => { Navigator.pushReplacementNamed( context, RoutesEnum.homePage, ), }, ), }, ), addVerticalSpace(20), RoundButton( title: "Toast", tapfun: () { toastmessage( authService.currentUser == null ? "NULL" : authService.currentUser!.email.toString(), ); }, ), ], ), ), Padding( padding: const EdgeInsets.all(30), child: Align( alignment: Alignment.bottomCenter, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( "Don't have an account?", style: TextStyle( color: Colors.white, ), ), TextButton( onPressed: () { Navigator.pushNamed( context, RoutesEnum.signUpPage, ); }, child: const Text("Sign Up"), ), ], ), ), ) ], ), ); } }
请问我哪里出错了?
解决方案
白屏问题主要由两个核心问题导致:
1. 参数冲突:同时设置nextScreen和nextRoute
AnimatedSplashScreen组件中,nextScreen(直接指定跳转Widget)和nextRoute(指定命名路由)是互斥的,不能同时设置。你当前同时传递了这两个参数,导致组件路由逻辑冲突,引发白屏。
2. 用户状态判断时机过早
在StatelessWidget的build方法中直接获取AuthService().currentUser,此时Firebase Auth可能还未完成初始化,拿到的用户状态不准确;且build方法会被多次调用,容易导致路由跳转逻辑混乱。
修复步骤:
步骤1:移除冲突参数
保留nextRoute(符合你使用命名路由的逻辑),删除nextScreen: LoginPage(),这一行:
return AnimatedSplashScreen( duration: 1500, splash: Icons.home, nextRoute: nextScreen, // 仅保留该参数 splashTransition: SplashTransition.rotationTransition, );
步骤2:异步处理用户状态判断
将SplashScreen改为StatefulWidget,在initState中异步获取用户状态,确保Firebase Auth初始化完成:
class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @override State<SplashScreen> createState() => _SplashScreenState(); } class _SplashScreenState extends State<SplashScreen> { late String _nextScreen; @override void initState() { super.initState(); _determineNextScreen(); } Future<void> _determineNextScreen() async { // 等待Firebase Auth初始化完成,确保用户状态准确 await Future.delayed(const Duration(milliseconds: 500)); final user = AuthService().currentUser; setState(() { _nextScreen = user != null ? RoutesEnum.homePage : RoutesEnum.loginPage; }); } @override Widget build(BuildContext context) { return AnimatedSplashScreen( duration: 1500, splash: Icons.home, nextRoute: _nextScreen, splashTransition: SplashTransition.rotationTransition, ); } }
步骤3:可选:添加背景色区分白屏
检查你的mainTheme是否设置了合适的背景色,如果主题背景为白色,可给AnimatedSplashScreen添加backgroundColor参数,避免启动图标与背景融合导致视觉上的白屏:
return AnimatedSplashScreen( duration: 1500, splash: Icons.home, nextRoute: _nextScreen, splashTransition: SplashTransition.rotationTransition, backgroundColor: Colors.blue, // 设置启动页背景色 );
完成以上修改后,即可解决白屏问题,正常显示启动动画并跳转到对应页面。
内容的提问来源于stack exchange,提问作者Anton Schrage
相关产品推荐
相关产品推荐

