Flutter实战 从头撸一个「孤岛」APP(No.二、闪屏Splash Page、引导页)

1. 前情回顾

嗨,正在掉头发的大家好,我是洋小洋,本集我们接着聊一下GooGle的“亲儿子”Flutter。那自从上篇文章分享以后,有一些掘友也发表了一些颇有意思的评论。那我们首先来回顾一下git

1.1 读读评论

在这里挑选3位的评论,以为挺有趣,毕竟咱也不是设计师,这也不得不证实了一个产品的UI是多么的重要,固然也是随机在评论区,贴上他们的连接,也能够看看对方会不会有什么技术上的专栏,你们互相学习。以后的每一段路,我也都对从评论区贴上大家的奇葩评论github

1.2 上集成就

  • 掘金社区Flutter模块7天内热榜第1算法

  • 掘金社区Flutter模块热门第3windows

  • 掘金社区Flutter模块最新第8markdown

  • 截止目前25赞10评论app

虽然我也不太喜欢掘金的搜索算法,据说更新了,期待愈来愈好,你们可以分享本身对于技术的探索框架

2. 写在前面

不知不觉一周又过去了,实际开发的过程当中仍是会有不少坑的,这个按部就班会和你们分享,包括像Provider和后台交互的流程等。Dio的企业化配置等。那在本集我们仍是画界面less

2.1 本章目标

如图所示,仍是那么一个Low的界面,下面的内容可能会有点无聊,不过真的很肝,期待与你相遇async

2.2 分享列表

2.3 Flutter数据

3. 着手开发

3.1 vscode 插件

  • Flutter 语法检测、代码补全、代码重构、运行调试和热重载
  • Dart
  • Flutter Widget Snippets Widget 代码片断
  • Awesome Flutter Snippets 提供经常使用函数的代码片断

那因为一个APP 一上来就直接登陆页或者注册页。是有点生硬的,对用户来讲是极为不友好的,凡事都要慢慢来,有个过程不是吗?其实在闪屏的过程当中,是会作一些判断的,你如判断用户有没有登陆等

3.2 拉取代码

发现咱们并无提交更新

  • 新建开发分支

接着我们新建一个开发分支,用来记录新的一个章节,这个章节我们要作的是闪屏和引导页,如题

  • DEBUG 调试

在上周的时候 咱们是经过在项目的根目录下flutter run运行项目,而后Rr进行切换

本周我们借助Vscode debug 调试模式

3.3 公共变量处理Global

在评论区,有掘友提到,底部的导航也太大,其实咱们是已经适配过屏幕的不是吗?经过一个插件flutter_screenutil,固然也能够采起其余的方式,好比MediaQuery能够拿到widget以及设备的的宽高

那么什么是全局变量呢, 全局变量就是单纯指会贯穿整个APP生命周期的变量,用于单纯的保存一些信息,或者封装一些全局工具和方法的对象。

咱们先打算新建一个global.dart用来存放好比说经常使用的宽度、高度、以及字体大小

cd utils
copy nul > global.dart // 新建一个global.dart(windows下)
复制代码
import 'package:flutter_screenutil/flutter_screenutil.dart';

/// 页面常见的宽度与高度
// 宽度
double width100 = ScreenUtil.getInstance().setWidth(100);
// 高度
double height100 = ScreenUtil.getInstance().setHeight(100);

复制代码

接着咱们在底部的导航栏看下直接用咱们的变量,固然第一步仍是引入

import '../utils/global.dart';
复制代码

咱们来进行测试下,把上一段结尾我们引入的图片所有先删除,写上一段测试文字

当咱们重启以后,显然是能够的

3.4 闪屏 splash screen

咱们第一步仍是新建一个page页面,并命名为splash_screen_page

/// 闪屏的页面
import 'package:flutter/material.dart';

class SplashScreenPage extends StatelessWidget {
  const SplashScreenPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Text('闪屏页面'),
      ),
    );
  }
}

复制代码

而后在main.dart引用并使用,这时咱们已经再也不引入底部的导航界面了

return MaterialApp(
        debugShowCheckedModeBanner: false, // 去除调试
        title: '孤岛',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: SplashScreenPage()); // 这里使用引导页,也就是说当用户一进来的时候,是一个闪屏
  }
复制代码

接着我们就写属于这个孤岛APP 闪屏页,首先了解下几个部件

  • SingleChildScrollView 主要是控制里边的部件溢出,能够进行滚动

  • BoxDecoration 主要是对容器进行修饰的,好比背景色,宽高等

这里咱们使用一下渐变 gradient

decoration: BoxDecoration(
            gradient: LinearGradient(
                colors: [
              // 线性渐变 有个渐变的过程
              Color.fromRGBO(0, 0, 0, 0.2),
              Color.fromRGBO(0, 0, 0, 0.4)
            ],
                begin: FractionalOffset.topCenter, // 顶部居中
                end: FractionalOffset.bottomCenter)), // 
复制代码

效果是这个样子的

这个时候应用的第一个页面即是闪屏页面,而后咱们写这个页面的主要内容

child: Container(
              child: Column(
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.only(top: 30),
                  ),
                    // 
                  Text('孤岛',
                      style: TextStyle(
                          fontSize: fontSize200, fontWeight: FontWeight.w600))
                ],
              ),
            ),
复制代码

这里注意,fontSize: fontSize200咱们直接使用公共的global的声明定义好的大小就可

好了 跑一下

不尽如意的是,报了错误

The method '/' was called on null.
复制代码

这个问题很简单,实际上是咱们在使用屏幕适配的时候,并无初始化

显然这样就能够了,咱们接着插入一张图片,放在这儿就会好些了

decoration: BoxDecoration(
            image: DecorationImage(
              image: AssetImage(assetName)
            )
          ),

复制代码

放什么图片呢,就仍是放一张保守点的吧,感受她愈来愈不像《孤岛App》了

**图片资源来自B站UP主 **wlop- (若有侵权,请联系 Blog

老规矩我们仍是须要在pubspec.yaml中配置一下,闪屏静态时候的样子我们暂且这个样子

0215

还记得咱们上一段旅程有一块儿看过MaterialApp 的源码

const MaterialApp({
    Key key,
    this.navigatorKey,
    this.home,
    this.routes = const <String, WidgetBuilder>{}, // 咱们暂时会用到这个路由的配置
    this.initialRoute,
    this.onGenerateRoute,
    this.onUnknownRoute,
    this.navigatorObservers = const <NavigatorObserver>[],
    this.builder,
    this.title = '',
    this.onGenerateTitle,
    this.color,
    this.theme,
    this.darkTheme,
    this.themeMode = ThemeMode.system,
    this.locale,
    this.localizationsDelegates,
    this.localeListResolutionCallback,
    this.localeResolutionCallback,
    this.supportedLocales = const <Locale>[Locale('en', 'US')],
    this.debugShowMaterialGrid = false,
    this.showPerformanceOverlay = false,
    this.checkerboardRasterCacheImages = false,
    this.checkerboardOffscreenLayers = false,
    this.showSemanticsDebugger = false,
    this.debugShowCheckedModeBanner = true,
  })

复制代码

主要目的即是当闪屏结束的时候,跳转到引导页面

return MaterialApp(
      debugShowCheckedModeBanner: false, // 去除调试
      title: '孤岛',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SplashScreenPage(),
      routes: {
        'guidePages': (context) {
          return GuidePages(); // 跳转到引导页面
        }
      },
    );

复制代码

设计一个计时器,用来等计时器结束的时候,跳转

/// 设计一个计时器,用来等计时器结束的时候,跳转
  jumpPage(){
    return Timer(duration, callback);
  }
/// 源码实际上是这样的
 factory Timer(Duration duration, void callback()) {
    if (Zone.current == Zone.root) {
      // No need to bind the callback. We know that the root's timer will
      // be invoked in the root zone.
      return Zone.current.createTimer(duration, callback);
    }
    return Zone.current
        .createTimer(duration, Zone.current.bindCallbackGuarded(callback));
  }

复制代码
  • duration 就是延迟
  • callback 就是回调,在时间结束作什么事情

因为以前我们是用的是StatelessWidget 也就是说咱们须要在一个时间调用页面跳转的方法暂时咱们改用有状态的部件StatefulWidget,完整代码是这样

import 'dart:async';

/// 闪屏的页面
import 'package:flutter/material.dart';
import '../utils/global.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class SplashScreenPage extends StatefulWidget {
  SplashScreenPage({Key key}) : super(key: key);

  @override
  _SplashScreenPageState createState() => _SplashScreenPageState();
}

class _SplashScreenPageState extends State<SplashScreenPage> {
  /// 设计一个计时器,用来等计时器结束的时候,跳转
  jumpPage() {
    return Timer(Duration(milliseconds: 3000), () {
      Navigator.pushReplacementNamed(context, 'guidePages');
    });
  }

  @override
  void initState() {
    super.initState();

    jumpPage();
  }

  @override
  Widget build(BuildContext context) {
    ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
    return Scaffold(
        backgroundColor: Colors.white, // 背景色
        body: Container(
          decoration: BoxDecoration(
              image: DecorationImage(
                  image: AssetImage('images/splash_screen.jpg'),
                  fit: BoxFit.cover)), // 添加背景图片
          child: Container(
            child: Center(
              child: SingleChildScrollView(
                child: Container(
                  child: Column(
                    children: <Widget>[
                      Padding(
                        padding: EdgeInsets.only(top: 30),
                      ),
                      Text('欢迎来到孤岛',
                          style: TextStyle(
                              fontSize: fontSize40,
                              color: Colors.white10,
                              fontWeight: FontWeight.w600)),
                      SizedBox(
                        height: height100,
                      ),
                      Text('By 洋小洋',
                          style: TextStyle(
                              fontSize: fontSize40,
                              color: Colors.white10,
                              fontWeight: FontWeight.w600))
                    ],
                  ),
                ),
              ),
            ),
            decoration: BoxDecoration(
                gradient: LinearGradient(
                    colors: [
                  // 线性渐变 有个渐变的过程
                  Color.fromRGBO(0, 0, 0, 0.2),
                  Color.fromRGBO(0, 0, 0, 0.5)
                ],
                    begin: FractionalOffset.topCenter, // 顶部居中
                    end: FractionalOffset.bottomCenter)), // 底部居中
          ),
        ));
  }
}


复制代码

好了,咱们先阶段性的看下一块儿实现的效果

3.5 引导页

在走过了闪屏以后,咱们指望能有个引导页,顾名思义就是引导用户下一步下一步,这里我们采用第三方的包intro_views_flutter 2.8.0

截止目前包的版本是2.8.0

包名 传送
intro_views_flutter intro_views_flutter
  • 将此添加到包的pubspec.yaml文件中:

    dependencies:
      intro_views_flutter: ^2.8.0
    
    复制代码
  • 您能够从命令行安装软件包:

    $ flutter pub get
    
    复制代码
  • 如今,在Dart代码中,您可使用:

    import 'package:intro_views_flutter/intro_views_flutter.dart';
    
    复制代码

一波流操做后,就能够是使用了,具体使用的方法仍是须要看一下API

属性 数据类型 描述 默认值
pageColor Color 设置页面的颜色。 Null
mainImage Image / Widget 设置页面的主图像。 Null
title Text / Widget 设置页面的标题文本。 Null
body Text / Widget 设置页面的正文。 Null
iconImageAssetPath String 设置将在页面气泡中显示的图标图像路径。 Null
iconColor Color 设置页面气泡图标的颜色。 Null
bubbleBackgroundColor Color 设置页面气泡背景色。 Colors.white / Color(0x88FFFFFF)
textStyle TextStyle 为标题和正文设置TextStyle title: color: Colors.white , fontSize: 50.0 body: color: Colors.white , fontSize: 24.0
titleTextStyle TextStyle 设置标题的TextStyle color: Colors.white , fontSize: 50.0
bodyTextStyle TextStyle 为正文设置TextStyle color: Colors.white , fontSize: 24.0
bubble Widget 为内部气泡设置自定义小部件 null

那我们就根据使用的小细则定义一个PageViewModel

PageViewModel(
        pageColor: const Color(0xFF03A9F4),
        // iconImageAssetPath: 'assets/air-hostess.png',
        iconColor: Colors.pink,
        bubbleBackgroundColor: Colors.pink,
        // bubble: Image.asset('images/jiche.jpg'),
        body: Text(
          '这是属于你个人孤岛',
        ),
        title: Text(
          'No.1',
        ),
        // titleTextStyle: TextStyle(fontFamily: 'MyFont', color: Colors.white),
        // bodyTextStyle: TextStyle(fontFamily: 'MyFont', color: Colors.white),
        mainImage: Container(
          decoration:
              BoxDecoration(border: Border.all(width: 1, color: Colors.red)),
          child: Image.asset(
            // 图片
            'images/jiche.jpg',
            height: width750,
            width: height1314,
            fit: BoxFit.cover,
            // alignment: Alignment.center, // 居中显示
          ),
        )),

复制代码

images文件夹我们又新增了几张图片,用于引导页的展现,图片素材有的是在这儿找的

那如今效果就差很少了,来一块儿看下

4. 写在最后

很高兴你能耐住性子看到这儿,尤为是在这个快节奏的生活和工做中,咱们在今天的这段旅程已经完成了两部分

  • 闪屏
  • 引导页

写到如今已是凌晨2:35分了

因为这周看了下这个

又出去浪荡了一圈,不过也尚未断更,也算对本身的一个激励吧,因此也请你给个鼓励,评论点赞,固然是感受还行的话,说不定就出如今下一章节的[读读评论]

我是洋小洋,下回见,本节代码会同步更新仓库 github.com/yayxs/flutt…


--END

相关文章
相关标签/搜索