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

相關文章
相關標籤/搜索