
上節(jié)我們簡單的處理了下程序的入口函數(shù)文件
main.dart,在其中我們讓程序啟動后進入的第一個頁面是閃屏頁SplashPage。現(xiàn)在市面上絕大多數(shù)App啟動后都會有個閃屏頁,一般都是展示一張應(yīng)用相關(guān)的圖片或是放置一個廣告位用來展示廣告以賺取收入。那么今天我們就來實現(xiàn)個簡單的閃屏頁。先來看看效果圖:

-
SplashPage
在lib目錄下新建一個目錄page,添加splash_page.dart,該界面主要實現(xiàn)如下功能:
1.放置一張圖片或動態(tài)圖(gif),類似于廣告展示圖;
2.右上角放置一個倒計時按鈕,默認顯示3s,3s內(nèi)點擊按鈕跳轉(zhuǎn)HomePage界面,否則倒計時結(jié)束后自動跳轉(zhuǎn)到HomePage界面。
-
背景圖
在根目錄下新建一個assets/images/目錄用來放置App中需要用到的圖片,我們在目錄下放置一張背景圖bg.png(上面gif動圖中的黑色背景圖,自己PS的圖片。),然后到根目錄下的pubspec.yaml文件中添加下面代碼
# The following section is specific to Flutter.
flutter:
assets:
- assets/images/
添加完之后再終端下執(zhí)行flutter pub get或點擊VSCode右上角的刷新按鈕也行,這樣我們就可以在代碼中引用剛剛添加的本地圖片了。
因為倒計時要不斷的刷新界面,所以SplashPage也是一個StatefulWidget。頁面的布局就是背景圖上再放置一個倒計時按鈕,這里使用Flutter的Stack部件,在該部件里我們可以在確定的位置放置我們想要放置的子部件。
-
倒計時功能實現(xiàn)
我們先來寫個倒計時的方法countDown,
countDown() async {
Timer(Duration(seconds: 1), () {
_timer = Timer.periodic(Duration(milliseconds: 1000), (t) {
count--;
if (count == 0) {
navigationToHome(); //跳轉(zhuǎn)到home頁
} else {
setState(() {}); //刷新界面
}
});
return _timer;
});
}
然后在initState(){}方法中調(diào)用countDown方法,這樣當(dāng)進入SplashPage界面就會執(zhí)行倒計時方法了,界面右上角上就會看到一個倒計時按鈕數(shù)字在變化。
-
跳轉(zhuǎn)Home界面
當(dāng)?shù)褂嫊r按鈕在3s內(nèi)未被點擊,則倒計時結(jié)束后自動跳轉(zhuǎn)到HomePage,當(dāng)在3s內(nèi)點擊按鈕則立馬跳轉(zhuǎn)到HomePage。下面我們寫個跳轉(zhuǎn)方法,該方法中首先要取消定時器Timer,具體如下:
navigationToHome() {
_timer.cancel();
Routes.navigateTo(context, '/home', clearStack: true);
}
有小伙伴可能要問Routes是什么鬼?這里是使用了一個第三方插件Fluro。在pubspec.yaml文件的dependencies:下添加fluro: ^1.6.3,然后終端執(zhí)行flutter pub get加載該插件。然后在lib目錄下新建一個router文件夾,里面新建兩個文件routes.dart和router_handler.dart,里面的內(nèi)容如下:
- routes.dart
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:icooker/router/router_handler.dart';
// 在routes.dart文件中配置路由,這里需要注意的事首頁一定要用“/”配置,其它頁無所謂
class Routes {
static Router router;
static String root = '/';
static String home = '/home';
static void configureRouters(Router router) {
router.notFoundHandler = Handler(
handlerFunc: (BuildContext context, Map<String, dynamic> params) {
print('ERROR====>>>>ROUTE WAS NOT FOUND!!!');
return;
});
router.define(home, handler: homeHandler); //首頁界面
}
// 對參數(shù)進行encode,解決參數(shù)中有特殊字符,影響fluro路由匹配
static Future navigateTo(BuildContext context, String path,
{Map<String, dynamic> params,
TransitionType transition = TransitionType.native,
bool clearStack = false}) {
String query = "";
if (params != null) {
int index = 0;
for (var key in params.keys) {
var value = Uri.encodeComponent(params[key]);
if (index == 0) {
query = "?";
} else {
query = query + "\&";
}
query += "$key=$value";
index++;
}
}
print('navigatorTo傳遞的參數(shù):$query');
path += query;
return router.navigateTo(context, path,
transition: transition, clearStack: clearStack);
}
//關(guān)閉當(dāng)前頁面
static pop(BuildContext context) {
router.pop(context);
}
}
其中的clearStack是否清理頁面棧,即從當(dāng)前頁面跳轉(zhuǎn)到新頁面后是否關(guān)閉前一個頁面。
true: 清除,即新頁面回退無法再進入跳轉(zhuǎn)前的頁面,
false: 不清除,即從新頁面按回退按鈕還能跳轉(zhuǎn)到之前的頁面。
- router_handler.dart
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:icooker/pages/home_page.dart';
Handler homeHandler =
Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
return HomePage();
});
然后再到main.dart文件中的build方法下添加如下代碼:
@override
Widget build(BuildContext context) {
// 配置路由
final router = Router();
Routes.configureRouters(router);
Routes.router = router;
... //省略
return MaterialApp(
debugShowCheckedModeBanner: false, //關(guān)閉banner上的Debug標識
onGenerateRoute: Routes.router.generator,
... // 省略
);
}
再在page目錄下新建一個 home_page.dart文件,里面隨便放置一個StatefulWidget即可,此時點擊VSCode上的調(diào)試按鈕就可以在模擬器或真機上看到閃屏頁的倒計時跳轉(zhuǎn)效果了。
-
解決Android啟動黑屏問題
在Android機器啟動后會出現(xiàn)幾秒黑屏現(xiàn)象,debug狀態(tài)下可能黑屏的時間更長,同時手機的配置越高黑屏的時間相對也越短。我們只需要執(zhí)行以下兩步:
- 在
android/app/src/main/res/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>
<bitmap
android:src="@mipmap/bg"/>
</item>
</layer-list>
添加一張跟閃屏頁相同的背景圖片即可
- 在
android/app/src/main/res/values/styles.xml文件中添加如下代碼:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:windowIsTranslucent">true</item>
</style>
</resources>
再重新debug下就會發(fā)現(xiàn)黑屏的問題解決了。(ps:建議調(diào)試的時候使用真機調(diào)試,模擬器太卡而且有些效果或問題只有真機上才能出現(xiàn)。)
好了,下面放出閃屏頁的完整參考代碼,如下:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:icooker/router/routes.dart';
class SplashPage extends StatefulWidget {
SplashPage({Key key}) : super(key: key);
@override
_SplashPageState createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> {
Timer _timer;
int count = 3; //默認倒計時3s
@override
void initState() {
super.initState();
countDown();
}
countDown() async {
Timer(Duration(seconds: 1), () {
_timer = Timer.periodic(Duration(milliseconds: 1000), (t) {
count--;
if (count == 0) {
navigationToHome(); //跳轉(zhuǎn)到home頁
} else {
setState(() {}); //刷新界面
}
});
return _timer;
});
}
navigationToHome() {
_timer.cancel();
Routes.navigateTo(context, '/home', clearStack: true);
}
@override
Widget build(BuildContext context) {
// debugPrint('count===$count');
return Stack(
alignment: Alignment(1.0, -1.0),
children: <Widget>[
ConstrainedBox(
constraints: BoxConstraints.expand(),
child: Image.asset(
'assets/images/bg.png',
fit: BoxFit.fill,
),
),
Padding(
padding: EdgeInsets.fromLTRB(0, 20.0, 4.0, 0),
child: FlatButton(
onPressed: () => navigationToHome(),
color: Colors.grey,
shape: CircleBorder(),
child: Text(
'${count}s',
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
),
),
),
),
],
);
}
}