Flutter 启动页+闪屏广告页+引导页
以下是SplashPage页面用到的开源组件
一个App通常都会有SplashPage页面,在这页面包含启动页、引导页(app简介说明)、闪屏广告页(点广告页跳转到相应H5页面)。
在Flutter实现引导页需要在MaterialApp home指定为SplashPage,在routes里面配置主界面MainPage。SplashPage切换到MainPage通过Navigator.of(context).pushReplacementNamed(‘/MainPage’)实现。
@override Widget build(BuildContext context) { return new MaterialApp( routes: { '/MainPage': (ctx) => MainPage(), }, home: new SplashPage(), ); } void _goMain() { Navigator.of(context).pushReplacementNamed('/MainPage'); }
SplashPage 简单介绍
SplashPage分为四层,默认启动图,引导图,广告图,倒计时跳过。
使用status来控制页面显示状态,status=0显示启动图,status=1显示广告图和倒计时跳过,status=2显示引导图。
解决应用白屏
修改原生的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 android:drawable="@mipmap/splash_bg"> </item> </layer-list>
如何实现跳转到广告H5按back回来是主界面
同时push主页和web页
Navigator.of(context).pushReplacementNamed('/MainPage'); Navigator.of(context).push(WebPageRoute);
引导页
引导页
启动页
启动页
闪屏广告页
闪屏广告页
Android扫码下载APK:
flutter_wanandroid
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( '立即体验', 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( '跳过 $_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。 } }