美文网首页Flutter
Flutter实战--美食App(二)

Flutter实战--美食App(二)

作者: SamBrother | 来源:发表于2020-07-16 15:21 被阅读0次
    镇楼美女

    上节我们简单的处理了下程序的入口函数文件main.dart,在其中我们让程序启动后进入的第一个页面是闪屏页SplashPage。现在市面上绝大多数App启动后都会有个闪屏页,一般都是展示一张应用相关的图片或是放置一个广告位用来展示广告以赚取收入。那么今天我们就来实现个简单的闪屏页。先来看看效果图:

    闪屏页
    • SplashPage

    lib目录下新建一个目录page,添加splash_page.dart,该界面主要实现如下功能:

    1.放置一张图片或动态图(gif),类似于广告展示图;
    2.右上角放置一个倒计时按钮,默认显示3s3s内点击按钮跳转HomePage界面,否则倒计时结束后自动跳转到HomePage界面。

    • 背景图
      在根目录下新建一个assets/images/目录用来放置App中需要用到的图片,我们在目录下放置一张背景图bg.png(上面gif动图中的黑色背景图,自己PS的图片。),然后到根目录下的pubspec.yaml文件中添加下面代码
    # The following section is specific to Flutter.
    flutter:
      assets:
       - assets/images/
    

    添加完之后再终端下执行flutter pub get或点击VSCode右上角的刷新按钮也行,这样我们就可以在代码中引用刚刚添加的本地图片了。

    因为倒计时要不断的刷新界面,所以SplashPage也是一个StatefulWidget。页面的布局就是背景图上再放置一个倒计时按钮,这里使用FlutterStack部件,在该部件里我们可以在确定的位置放置我们想要放置的子部件。

    • 倒计时功能实现
      我们先来写个倒计时的方法countDown
    countDown() async {
        Timer(Duration(seconds: 1), () {
          _timer = Timer.periodic(Duration(milliseconds: 1000), (t) {
            count--;
            if (count == 0) {
              navigationToHome(); //跳转到home页
            } else {
              setState(() {}); //刷新界面
            }
          });
          return _timer;
        });
      }
    

    然后在initState(){}方法中调用countDown方法,这样当进入SplashPage界面就会执行倒计时方法了,界面右上角上就会看到一个倒计时按钮数字在变化。

    • 跳转Home界面
      当倒计时按钮在3s内未被点击,则倒计时结束后自动跳转到HomePage,当在3s内点击按钮则立马跳转到HomePage。下面我们写个跳转方法,该方法中首先要取消定时器Timer,具体如下:
    navigationToHome() {
        _timer.cancel();
        Routes.navigateTo(context, '/home', clearStack: true);
      }
    

    有小伙伴可能要问Routes是什么鬼?这里是使用了一个第三方插件Fluro。在pubspec.yaml文件的dependencies:下添加fluro: ^1.6.3,然后终端执行flutter pub get加载该插件。然后在lib目录下新建一个router文件夹,里面新建两个文件routes.dartrouter_handler.dart,里面的内容如下:

    • routes.dart
    import 'package:fluro/fluro.dart';
    import 'package:flutter/material.dart';
    import 'package:icooker/router/router_handler.dart';
    
    // 在routes.dart文件中配置路由,这里需要注意的事首页一定要用“/”配置,其它页无所谓
    class Routes {
      static Router router;
    
      static String root = '/';
      static String home = '/home';
    
      static void configureRouters(Router router) {
        router.notFoundHandler = Handler(
            handlerFunc: (BuildContext context, Map<String, dynamic> params) {
          print('ERROR====>>>>ROUTE WAS NOT FOUND!!!');
          return;
        });
    
        router.define(home, handler: homeHandler); //首页界面
      }
    
      // 对参数进行encode,解决参数中有特殊字符,影响fluro路由匹配
      static Future navigateTo(BuildContext context, String path,
          {Map<String, dynamic> params,
          TransitionType transition = TransitionType.native,
          bool clearStack = false}) {
         
        String query = "";
        if (params != null) {
          int index = 0;
          for (var key in params.keys) {
            var value = Uri.encodeComponent(params[key]);
            if (index == 0) {
              query = "?";
            } else {
              query = query + "\&";
            }
            query += "$key=$value";
            index++;
          }
        }
        print('navigatorTo传递的参数:$query');
        path += query;
        return router.navigateTo(context, path,
            transition: transition, clearStack: clearStack);
      }
    
      //关闭当前页面
      static pop(BuildContext context) {
        router.pop(context);
      }
    }
    

    其中的clearStack是否清理页面栈,即从当前页面跳转到新页面后是否关闭前一个页面。

    true: 清除,即新页面回退无法再进入跳转前的页面,
    false: 不清除,即从新页面按回退按钮还能跳转到之前的页面。
    
    • router_handler.dart
    import 'package:fluro/fluro.dart';
    import 'package:flutter/material.dart';
    import 'package:icooker/pages/home_page.dart';
    
    Handler homeHandler =
        Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
      return HomePage();
    });
    

    然后再到main.dart文件中的build方法下添加如下代码:

    @override
      Widget build(BuildContext context) {
        // 配置路由
        final router = Router();
        Routes.configureRouters(router);
        Routes.router = router;
        ... //省略
        return MaterialApp(
              debugShowCheckedModeBanner: false, //关闭banner上的Debug标识
              onGenerateRoute: Routes.router.generator,
              ... // 省略
         );
      }
    

    再在page目录下新建一个 home_page.dart文件,里面随便放置一个StatefulWidget即可,此时点击VSCode上的调试按钮就可以在模拟器或真机上看到闪屏页的倒计时跳转效果了。

    • 解决Android启动黑屏问题
      在Android机器启动后会出现几秒黑屏现象,debug状态下可能黑屏的时间更长,同时手机的配置越高黑屏的时间相对也越短。我们只需要执行以下两步:
    • android/app/src/main/res/drawable/launch_background.xml中添加如下代码:
    <?xml version="1.0" encoding="utf-8"?>
    <!-- Modify this file to customize your launch splash screen -->
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@android:color/white" />
    
        <!-- You can insert your own image assets here -->
        <!-- <item>
            <bitmap
                android:gravity="center"
                android:src="@mipmap/launch_image" />
        </item> -->
        <item>
            <bitmap 
            android:src="@mipmap/bg"/>
        </item>
    </layer-list>
    

    添加一张跟闪屏页相同的背景图片即可

    • android/app/src/main/res/values/styles.xml文件中添加如下代码:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
            <!-- Show a splash screen on the activity. Automatically removed when
                 Flutter draws its first frame -->
            <item name="android:windowBackground">@drawable/launch_background</item>
            <item name="android:windowIsTranslucent">true</item>
        </style>
    </resources>
    

    再重新debug下就会发现黑屏的问题解决了。(ps:建议调试的时候使用真机调试,模拟器太卡而且有些效果或问题只有真机上才能出现。)

    好了,下面放出闪屏页的完整参考代码,如下:

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    import 'package:icooker/router/routes.dart';
    
    class SplashPage extends StatefulWidget {
      SplashPage({Key key}) : super(key: key);
    
      @override
      _SplashPageState createState() => _SplashPageState();
    }
    
    class _SplashPageState extends State<SplashPage> {
      Timer _timer;
      int count = 3; //默认倒计时3s
    
      @override
      void initState() {
        super.initState();
        countDown();
      }
    
      countDown() async {
        Timer(Duration(seconds: 1), () {
          _timer = Timer.periodic(Duration(milliseconds: 1000), (t) {
            count--;
            if (count == 0) {
              navigationToHome(); //跳转到home页
            } else {
              setState(() {}); //刷新界面
            }
          });
          return _timer;
        });
      }
    
      navigationToHome() {
        _timer.cancel();
        Routes.navigateTo(context, '/home', clearStack: true);
      }
    
      @override
      Widget build(BuildContext context) {
        // debugPrint('count===$count');
        return Stack(
          alignment: Alignment(1.0, -1.0),
          children: <Widget>[
            ConstrainedBox(
              constraints: BoxConstraints.expand(),
              child: Image.asset(
                'assets/images/bg.png',
                fit: BoxFit.fill,
              ),
            ),
            Padding(
              padding: EdgeInsets.fromLTRB(0, 20.0, 4.0, 0),
              child: FlatButton(
                onPressed: () => navigationToHome(),
                color: Colors.grey,
                shape: CircleBorder(),
                child: Text(
                  '${count}s',
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 14.0,
                  ),
                ),
              ),
            ),
          ],
        );
      }
    }
    

    ☞完整Demo请移步 iCooker 喜欢的请给个Star ☆!!

    相关文章

      网友评论

        本文标题:Flutter实战--美食App(二)

        本文链接:https://www.haomeiwen.com/subject/irhphktx.html