【问题标题】:Flutter hold splash screen for 3 Seconds. How to implement splash screen in Flutter?Flutter 按住闪屏 3 秒。如何在 Flutter 中实现闪屏?
【发布时间】:2018-10-12 06:36:29
【问题描述】:

如何在颤动中显示启动屏幕 3 秒,然后转到下一个我的登录屏幕。

我已经尝试过.countdowntimer 但导入未解决

import 'package: countDown/countDown.dart';
CountDown cd  =  new CountDown(new Duration(seconds: 4));
CountDown is unresolved 

Android Studio 和 Flutter

【问题讨论】:

    标签: android ios android-studio flutter splash-screen


    【解决方案1】:

    您可以使用 Future.delayed 延迟执行代码

    new Future.delayed(const Duration(seconds: 3), () {
      Navigator.pushNamed(context, '/login');
    });
    

    更新

    const delay = 3;
    widget.countdown = delay;
    
    StreamSubscription sub;
    sub = new Stream.periodic(const Duration(seconds: 1), (count) {
      setState(() => widget.countdown--);  
      if(widget.countdown <= 0) {
        sub.cancel();
        Navigator.pushNamed(context, '/login');
      }
    });     
    

    【讨论】:

    • 但是倒计时有什么办法呢?
    • 为什么不呢? . . . .
    • 因为你必须手动更新倒计时。如果您想显示秒/毫秒,则必须更改刷新刻度。使用带有倒计时持续时间的 AnimationControllerAnimatedBuilder 将提供更大的灵活性,而不必费心刷新。
    • 听起来很合理。
    • 我应该在哪里调用这个未来代码。我的意思是我不想点击
    【解决方案2】:

    Future.delayed 将是一个很好的解决方案没有倒计时。

    但考虑到你有倒计时,你可以使用 Flutter 提供的动画框架。

    其背后的想法是使用持续时间为 3 秒的AnimationController。实例化 splashScreen 后立即启动动画。并添加一个监听器以在动画结束时重定向到/login

    然后将该控制器传递给AnimationBuilder,它将根据animationController.lastElaspedDuration 处理您的倒计时格式。

    class SplashScreen extends StatefulWidget {
      final Duration duration;
    
      const SplashScreen({this.duration});
    
      @override
      _SplashScreenState createState() => new _SplashScreenState();
    }
    
    class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderStateMixin {
      AnimationController animationController;
    
      @override
      void initState() {
        animationController = new AnimationController(duration: widget.duration, vsync: this)
          ..forward()
          ..addStatusListener((status) {
            if (status == AnimationStatus.completed) {
              Navigator.pushReplacementNamed(context, '/login');
            }
          });
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return new AnimatedBuilder(
          animation: animationController,
          builder: (context, _) {
            return new Center(
              child: new Text(animationController.lastElapsedDuration.inSeconds.toString()),
            );
          },
        );
      }
    }
    

    【讨论】:

      【解决方案3】:

      我认为您需要从堆栈中清除旧活动(启动画面),因此您必须使用 pushNamedAndRemoveUntil 而不是仅使用 pushNamed

        new Future.delayed(const Duration(seconds: 3), () {
        Navigator.pushNamedAndRemoveUntil(context, '/login', ModalRoute.withName('/'));
      });
      

      【讨论】:

      • 或使用pushReplacementNamed
      【解决方案4】:

      参考下面main.dart

      import 'dart:async';    
      import 'package:flutter/material.dart';    
      import 'src/login_screen.dart';
      
      void main() {
        runApp(new MaterialApp(
          home: new MyApp(),
        ));
      }
      
      class MyApp extends StatefulWidget {
        @override
        _MyAppState createState() => new _MyAppState();
      }
      
      class _MyAppState extends State<MyApp> {
        @override
        void initState() {
          super.initState();
          new Future.delayed(
              const Duration(seconds: 3),
              () => Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => LoginScreen()),
                  ));
        }
      
        @override
        Widget build(BuildContext context) {
          return new Scaffold(
            backgroundColor: Colors.white,
            body: Container(
              child: new Column(children: <Widget>[
                Divider(
                  height: 240.0,
                  color: Colors.white,
                ),
                new Image.asset(
                  'assets/logo.png',
                  fit: BoxFit.cover,
                  repeat: ImageRepeat.noRepeat,
                  width: 170.0,
                ),
                Divider(
                  height: 105.2,
                  color: Colors.white,
                ),
              ]),
            ),
          );
        }
      }
      

      希望对你有帮助

      【讨论】:

        【解决方案5】:

        此答案仅适用于您使用flutter-redux 的情况。

        除了flutter-redux,您还需要使用redux-persist 库来显示加载屏幕。

        redux-persist 用于存储、补充应用状态。

        示例:

        1.main.dart

        import 'package:flutter/material.dart';
        import 'package:flutter/foundation.dart';
        import 'package:flutter_redux/flutter_redux.dart';
        import 'package:redux_persist_flutter/redux_persist_flutter.dart';
        
        import 'package:flutter_redux_starter/presentation/platform_adaptive.dart';
        import 'package:flutter_redux_starter/screens/loading_screen.dart';
        import 'package:flutter_redux_starter/store/store.dart';
        import 'package:flutter_redux_starter/middleware/middleware.dart';
        import 'package:flutter_redux_starter/models/app_state.dart';
        import 'package:flutter_redux_starter/routes.dart';
        
        
        void main() => runApp(new MyApp());
        
        class MyApp extends StatelessWidget {
            final store = createStore();
        
            MyApp();
        
            @override
            Widget build(BuildContext context) {
                return new PersistorGate(
                    persistor: persistor,
                    loading: new LoadingScreen(),
                    builder: (context) => new StoreProvider<AppState>(
                        store: store,
                        child: new MaterialApp(
                            title: 'Flutter test App',
                            theme: defaultTargetPlatform == TargetPlatform.iOS
                                ? kIOSTheme
                                : kDefaultTheme,
                        routes: getRoutes(context, store),
                            initialRoute: '/login',
                        )
                    ),
                );
            }
        
        }
        

        2.store.dart

        import 'package:redux/redux.dart';
        
        import 'package:flutter_redux_starter/reducers/app_reducer.dart';
        import 'package:flutter_redux_starter/models/app_state.dart';
        import 'package:flutter_redux_starter/middleware/middleware.dart';
        
        Store<AppState> createStore() { 
            Store<AppState> store = new Store(
                appReducer,
                initialState: new AppState(),
                middleware: createMiddleware(),
            );
            persistor.start(store);
        
            return store;
        }
        

        在 createStore 中,您可以使用 Future.delayed 将商店的创建延迟一定的秒数。

        new Future.delayed(const Duration(seconds: 3), () {
         // 
        });
        

        【讨论】:

          【解决方案6】:

          您可以在initState 中使用Future.delayed 构造函数。这将使您的 SplashScreen 在导航发生之前保持您指定的持续时间。

          class SplashScreen extends StatefulWidget {
            @override
            _SplashScreenState createState() => new _SplashScreenState();
          }
          
          class _SplashScreenState extends State<SplashScreen> {
            @override
            void initState (){
              super.initState();
              // TODO initial state stuff
              new Future.delayed(const Duration(seconds: 4));
            }
            @override
            Widget build(BuildContext context) {
              //build
            }
          }
          

          我只复制了来自:this的答案

          【讨论】:

            【解决方案7】:

            我在每个应用程序中使用的简单解决方案。

            在构建方法中使用Timer 类 代码sn-p

            class SplashScreen extends StatefulWidget {
              @override
              Splash createState() => Splash();
            }
            
            class Splash extends State<SplashScreen>  {
            
              @override
              void initState() {
                super.initState();
            
              }
              @override
              Widget build(BuildContext context) {
                    Timer(
                        Duration(seconds: 3),
                            () =>
                        Navigator.of(context).pushReplacement(MaterialPageRoute(
                            builder: (BuildContext context) => LandingScreen())));
            
            
                var assetsImage = new AssetImage(
                    'images/new_logo.png'); //<- Creates an object that fetches an image.
                var image = new Image(
                    image: assetsImage,
                    height:300); //<- Creates a widget that displays an image.
            
                return MaterialApp(
                  home: Scaffold(
                    /* appBar: AppBar(
                      title: Text("MyApp"),
                      backgroundColor:
                          Colors.blue, //<- background color to combine with the picture :-)
                    ),*/
                    body: Container(
                      decoration: new BoxDecoration(color: Colors.white),
                      child: new Center(
                        child: image,
                      ),
                    ), //<- place where the image appears
                  ),
                );
              }
            }
            

            【讨论】:

            • 如果我按下返回按钮。我不会回到启动画面吗?
            • 按下返回键的时候是什么情况?你能告诉我,以便我更新答案
            • 现在好了。我不知道pushReplacement() 方法。但是我做了一件很奇怪的事。在 main.dart 中,我定义了LandingScreen(),然后在它的initState() 中,我将pushReplacement 定义为SplashScreen()。 SplashScreen 有您在此处提供的此代码。我试图在不改变家的情况下实现这一目标:main.dart。结果出现了各种各样的错误。
            • 好的,我知道了。我在 main 之后提供了第一个屏幕 ..如果你想让我提供 main.dart 类,我也可以更新代码
            • 您需要使用后台插件在后台执行任务,但后台插件可能无法在IOS中使用,如果我必须在后台获取数据,我会寻找其他方式跨度>
            【解决方案8】:

            我需要一个延迟 5 秒的小部件。我的解决方案如下:

            class Waiting extends StatefulWidget {
              @override
              _WaitingState createState() => _WaitingState();
            }
            
            class _WaitingState extends State<Waiting> {
              bool voxt = false;
            
              @override
              Widget build(BuildContext context) {
                return FutureBuilder(
                  future: Future.delayed(Duration(seconds: 3)),
                  builder: (c, s) => s.connectionState != ConnectionState.done
                      ? Text('Waiting')
                      : Text('3 sec passed')
                );
              }
            }
            

            现在可以在需要的地方调用Waiting小部件。

            【讨论】:

              【解决方案9】:

              最简洁的方法,无需添加显式计时器。

              使用基于时间的SplashScreen

              class TimeBasedSplash extends State<MyApp>{
              
                @override
                Widget build(BuildContext context) {
                  return new SplashScreen(
                    seconds: 10,
                    navigateAfterSeconds: new HomeScreen(),// Where to navigate after 10 secs
                    image: new Image.asset('assets/images/flutter_logo.png'),
                    photoSize: 200,
                    loaderColor: Colors.white,
                    styleTextUnderTheLoader : const TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold, color: Colors.white),
                   loadingText: new Text('Loading...'),
                    gradientBackground: LinearGradient(
                      begin: Alignment.topCenter,
                      end: Alignment.bottomCenter,
                      colors: <Color>[
                        Colors.lightBlue,
                        Colors.indigo
                      ],
                    ),
                  );
                }
              
              }
              

              在主类中

              void main(){
                runApp(new MaterialApp(
                  home: new MyApp(),
                ));
              }
              
              
              class MyApp extends StatefulWidget {
                @override
                _MyAppState createState() => new _MyAppState();
              }
              
              class _MyAppState extends State<MyApp> {
                @override
                Widget build(BuildContext context) {
                  return new TimeBasedSplash().build(context);
                }
              }
              

              【讨论】:

                【解决方案10】:

                您还可以在StatlessWidget() 中创建splashScreen。在home下MaterialApp()里面:

                home: FutureBuilder(
                        future: Future.delayed(Duration(seconds: 3)),
                        builder: (ctx, timer) => timer.connectionState == ConnectionState.done
                            ? ProfileScreen() //Screen to navigate to once the splashScreen is done.
                            : Container(
                                color: Colors.white,
                                child: Image(
                                  image: AssetImage('assets/images/download.png'),
                                ),
                              )),
                

                【讨论】:

                  猜你喜欢
                  • 2019-07-01
                  • 2022-10-19
                  • 1970-01-01
                  • 2021-10-17
                  • 2022-10-05
                  • 2020-10-04
                  • 2021-11-07
                  • 2021-11-21
                  • 2020-09-03
                  相关资源
                  最近更新 更多