SplashPage页面用到的开源组件
SharedPreferences 工具类 SpUtil
引导Banner Swiper
倒计时工具类TimerUtil
一个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);
引导页
启动页
闪屏广告页
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。
}
}