Flutter實(shí)現(xiàn)啟動(dòng)頁(yè)、閃屏廣告頁(yè)、引導(dǎo)頁(yè)

SplashPage頁(yè)面用到的開(kāi)源組件
SharedPreferences 工具類 SpUtil
引導(dǎo)Banner Swiper
倒計(jì)時(shí)工具類TimerUtil
一個(gè)App通常都會(huì)有SplashPage頁(yè)面,在這頁(yè)面包含啟動(dòng)頁(yè)、引導(dǎo)頁(yè)(app簡(jiǎn)介說(shuō)明)、閃屏廣告頁(yè)(點(diǎn)廣告頁(yè)跳轉(zhuǎn)到相應(yīng)H5頁(yè)面)。
在Flutter實(shí)現(xiàn)引導(dǎo)頁(yè)需要在MaterialApp home指定為SplashPage,在routes里面配置主界面MainPage。SplashPage切換到MainPage通過(guò)Navigator.of(context).pushReplacementNamed('/MainPage')實(shí)現(xiàn)。

@override
  Widget build(BuildContext context) {
    return new MaterialApp(
      routes: {
        '/MainPage': (ctx) => MainPage(),
      },
      home: new SplashPage(),
    );
  }

  void _goMain() {
    Navigator.of(context).pushReplacementNamed('/MainPage');
  }

SplashPage 簡(jiǎn)單介紹

SplashPage分為四層,默認(rèn)啟動(dòng)圖,引導(dǎo)圖,廣告圖,倒計(jì)時(shí)跳過(guò)。
使用status來(lái)控制頁(yè)面顯示狀態(tài),status=0顯示啟動(dòng)圖,status=1顯示廣告圖和倒計(jì)時(shí)跳過(guò),status=2顯示引導(dǎo)圖。

解決應(yīng)用白屏

修改原生的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> -->
     //這樣寫可以通過(guò)圖片鋪滿整個(gè)屏幕,不同屏幕可能會(huì)有拉伸
    <item android:drawable="@mipmap/splash_bg">
    </item>
</layer-list>

如何實(shí)現(xiàn)跳轉(zhuǎn)到廣告H5按back回來(lái)是主界面

同時(shí)push主頁(yè)和web頁(yè)

 Navigator.of(context).pushReplacementNamed('/MainPage');
 Navigator.of(context).push(WebPageRoute);

引導(dǎo)頁(yè)

引導(dǎo)頁(yè)

啟動(dòng)頁(yè)

啟動(dòng)頁(yè)

閃屏廣告頁(yè)

閃屏廣告頁(yè)

SplashPage源碼

import 'package:flutter/material.dart';
import 'package:flutter_wanandroid/common/component_index.dart';
import 'package:rxdart/rxdart.dart';

class SplashPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new SplashPageState();
  }
}

class SplashPageState extends State<SplashPage> {
  TimerUtil _timerUtil;

  List<String> _guideList = [
    Utils.getImgPath('guide1'),
    Utils.getImgPath('guide2'),
    Utils.getImgPath('guide3'),
    Utils.getImgPath('guide4'),
  ];

  List<Widget> _bannerList = new List();

  int _status = 0;
  int _count = 3;

  SplashModel _splashModel;

  @override
  void initState() {
    super.initState();
    _loadSplashData();
    _initAsync();
  }

  void _loadSplashData() async {
    HttpUtil httpUtil = new HttpUtil();
    httpUtil.getSplash().then((model) async {
      await SpUtil.getInstance();
      _splashModel = SpHelper.getSplashModel();
      if (!ObjectUtil.isEmpty(model.imgUrl)) {
        if (_splashModel == null || (_splashModel.imgUrl != model.imgUrl)) {
          SpUtil.putString(Constant.KEY_SPLASH_MODEL, json.encode(model));
          setState(() {
            _splashModel = model;
          });
        }
      } else {
        SpUtil.putString(Constant.KEY_SPLASH_MODEL, '');
      }
    });
  }

  void _initAsync() {
    Observable.just(1).delay(new Duration(milliseconds: 1000)).listen((_) {
      if (SpUtil.getBool(Constant.KEY_GUIDE) != true &&
          ObjectUtil.isNotEmpty(_guideList)) {
        SpUtil.putBool(Constant.KEY_GUIDE, true);
        _initBanner();
      } else {
        _initSplash();
      }
    });
  }

  void _initBanner() {
    _initBannerData();
    setState(() {
      _status = 2;
    });
  }

  void _initBannerData() {
    for (int i = 0, length = _guideList.length; i < length; i++) {
      if (i == length - 1) {
        _bannerList.add(new Stack(
          children: <Widget>[
            new Image.asset(
              _guideList[I],
              fit: BoxFit.fill,
              width: double.infinity,
              height: double.infinity,
            ),
            new Align(
              alignment: Alignment.bottomCenter,
              child: new Container(
                margin: EdgeInsets.only(bottom: 160.0),
                child: new RaisedButton(
                  textColor: Colors.white,
                  color: Colors.indigoAccent,
                  child: Text(
                    '立即體驗(yàn)',
                    style: new TextStyle(fontSize: 16.0),
                  ),
                  onPressed: () {
                    _goMain();
                  },
                ),
              ),
            ),
          ],
        ));
      } else {
        _bannerList.add(new Image.asset(
          _guideList[I],
          fit: BoxFit.fill,
          width: double.infinity,
          height: double.infinity,
        ));
      }
    }
  }

  void _initSplash() {
    _splashModel = SpHelper.getSplashModel();
    if (_splashModel == null) {
      _goMain();
    } else {
      _doCountDown();
    }
  }

  void _doCountDown() {
    setState(() {
      _status = 1;
    });
    _timerUtil = new TimerUtil(mTotalTime: 3 * 1000);
    _timerUtil.setOnTimerTickCallback((int tick) {
      double _tick = tick / 1000;
      setState(() {
        _count = _tick.toInt();
      });
      if (_tick == 0) {
        _goMain();
      }
    });
    _timerUtil.startCountDown();
  }

  void _goMain() {
    Navigator.of(context).pushReplacementNamed('/MainPage');
  }

  Widget _buildSplashBg() {
    return new Image.asset(
      Utils.getImgPath('splash_bg'),
      width: double.infinity,
      fit: BoxFit.fill,
      height: double.infinity,
    );
  }

  Widget _buildAdWidget() {
    if (_splashModel == null) {
      return new Container(
        height: 0.0,
      );
    }
    return new Offstage(
      offstage: !(_status == 1),
      child: new InkWell(
        onTap: () {
          if (ObjectUtil.isEmpty(_splashModel.url)) return;
          _goMain();
          NavigatorUtil.pushWeb(context,
              title: _splashModel.title, url: _splashModel.url);
        },
        child: new Container(
          alignment: Alignment.center,
          child: new CachedNetworkImage(
            width: double.infinity,
            height: double.infinity,
            fit: BoxFit.fill,
            imageUrl: _splashModel.imgUrl,
            placeholder: _buildSplashBg(),
            errorWidget: _buildSplashBg(),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Material(
      child: new Stack(
        children: <Widget>[
          new Offstage(
            offstage: !(_status == 0),
            child: _buildSplashBg(),
          ),
          new Offstage(
            offstage: !(_status == 2),
            child: ObjectUtil.isEmpty(_bannerList)
                ? new Container()
                : new Swiper(
                    autoStart: false,
                    circular: false,
                    indicator: CircleSwiperIndicator(
                      radius: 4.0,
                      padding: EdgeInsets.only(bottom: 30.0),
                      itemColor: Colors.black26,
                    ),
                    children: _bannerList),
          ),
         // _buildAdWidget(),
          new Offstage(
            offstage: !(_status == 1),
            child: _splashModel == null
                ? new Container()
                : new InkWell(
                    onTap: () {
                      if (ObjectUtil.isEmpty(_splashModel.url)) return;
                      _goMain();
                      NavigatorUtil.pushWeb(context,
                          title: _splashModel.title, url: _splashModel.url);
                    },
                    child: new Container(
                      alignment: Alignment.center,
                      child: new CachedNetworkImage(
                        width: double.infinity,
                        height: double.infinity,
                        fit: BoxFit.fill,
                        imageUrl: _splashModel.imgUrl,
                        placeholder: _buildSplashBg(),
                        errorWidget: _buildSplashBg(),
                      ),
                    ),
                  ),
          ),
          new Offstage(
            offstage: !(_status == 1),
            child: new Container(
              alignment: Alignment.bottomRight,
              margin: EdgeInsets.all(20.0),
              child: InkWell(
                onTap: () {
                  _goMain();
                },
                child: new Container(
                    padding: EdgeInsets.all(12.0),
                    child: new Text(
                      '跳過(guò) $_count',
                      style: new TextStyle(fontSize: 14.0, color: Colors.white),
                    ),
                    decoration: new BoxDecoration(
                        color: Color(0x66000000),
                        borderRadius: BorderRadius.all(Radius.circular(4.0)),
                        border: new Border.all(
                            width: 0.33, color: ColorT.divider))),
              ),
            ),
          )
        ],
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    if (_timerUtil != null) _timerUtil.cancel(); //記得中dispose里面把timer cancel。
  }
}

我的?????? : Flutter開(kāi)源庫(kù)集合

GitHub : flutter_wanandroid

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 冷啟動(dòng)(cold start) 冷啟動(dòng)是指應(yīng)用尚未運(yùn)行,系統(tǒng)創(chuàng)建進(jìn)程并初始化應(yīng)用。 熱啟動(dòng)是指應(yīng)用已經(jīng)運(yùn)行但是在后...
    reezy閱讀 18,116評(píng)論 1 67
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,659評(píng)論 4 61
  • 影沒(méi)有動(dòng) 光在動(dòng) 光沒(méi)在動(dòng) 云在動(dòng) 云沒(méi)在動(dòng) 風(fēng)在動(dòng) 風(fēng)沒(méi)在動(dòng) 我看著你 眼沒(méi)動(dòng) 心在動(dòng)
    北嶼丿閱讀 390評(píng)論 5 8
  • 沒(méi)有什么一定的吧,就像感冒了,不能寄托于打針吃藥,你以為會(huì)好,可是總是還會(huì)晚一點(diǎn),再晚一點(diǎn)。
    DZYES閱讀 155評(píng)論 0 0
  • 第二天,我專門早起去樓下買了早點(diǎn)。莫藍(lán)還沒(méi)有醒,她熟睡的樣子很親,像一個(gè)蜷縮的小貓。她沒(méi)有化妝的樣子很清純,大大的...
    左耳莫沫閱讀 1,294評(píng)論 3 1

友情鏈接更多精彩內(nèi)容