1. SplashScreen是什么?
启动屏幕(也叫闪屏)是用户在启动应用程序时看到的第一个屏幕。它也可以是应用程序的欢迎屏幕,当启动手机游戏或程序时,它提供了简单的初始体验。启动屏幕(闪屏)有时用于向用户显示在准备使用之前正在加载到内存中的应用程序的状态。
以下是启动画面的一些基本功能:
- 它主要用于应用程序的品牌或身份识别,并将品牌印象或播发广告给用户。
- 它还用于显示正在加载到内存中以向用户展示软件的应用程序的进度。
- 当启动屏幕的加载完成时,用户将获得另一个功能屏幕,该功能屏幕可能是主屏幕或仪表板,然后被遗忘了。加载完成后,无法按返回按钮返回启动画面。
2. SplashScreen库
在本文中,将演示使用社区提供的启动画面库。它在标准Flutter库中不可用,因此,如果要使用它,则必须在项目中声明它。
打开pubspec.yaml
文件,并在项目中声明启动画面库:
pubspec.yaml
.....
dependencies:
flutter:
sdk: flutter
splashscreen: ^1.3.5
下面的链接中看到其他版本或最新版本的启动画面库:
SplashScreen类提供了三个构造函数:
@protected
SplashScreen(
{Color loaderColor,
Future navigateAfterFuture,
int seconds,
double photoSize,
Route pageRoute,
dynamic onClick,
dynamic navigateAfterSeconds,
Text title: const Text(''),
Color backgroundColor: Colors.white,
TextStyle styleTextUnderTheLoader:
const TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold, color: Colors.black),
Image image,
Text loadingText: const Text(""),
ImageProvider<Object> imageBackground,
Gradient gradientBackground,
bool useLoader: true,
String routeName}
)
SplashScreen.network构造函数
SplashScreen.network(
{@required Future navigateAfterFuture,
Color loaderColor,
Color backgroundColor,
double photoSize,
Text loadingText,
Image image,
Route pageRoute,
dynamic onClick,
dynamic navigateAfterSeconds,
Text title,
TextStyle styleTextUnderTheLoader,
ImageProvider<Object> imageBackground,
Gradient gradientBackground,
bool useLoader,
String routeName}
)
SplashScreen.timer构造函数
SplashScreen.timer(
{@required int seconds,
Color loaderColor,
Color backgroundColor,
double photoSize,
Text loadingText,
Image image,
Route pageRoute,
dynamic onClick,
dynamic navigateAfterSeconds,
Text title,
TextStyle styleTextUnderTheLoader,
ImageProvider<Object> imageBackground,
Gradient gradientBackground,
bool useLoader,
String routeName}
)
下面是SplashScreen布局:
3. 示例:倒计时基础
首先,从一个简单的示例开始,在指定的时间内显示启动画面。稍后,它将被主应用程序屏幕替换。预览示例的结果如下:
首先,创建一个Flutter项目,并如上所述在项目中声明启动画面库。接下来,打开main.dart
文件,并将其内容替换为以下代码:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:splashscreen/splashscreen.dart';
void main() { runApp(MyApp()); }
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SplashScreenPage(),
debugShowCheckedModeBanner: false,
);
}
}
class SplashScreenPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SplashScreen(
seconds: 5,
navigateAfterSeconds: new HomeScreen(),
backgroundColor: Colors.green,
title: new Text('yiibai.com',textScaleFactor: 2,),
image: new Image.network(
'https://s3.o7planning.com/images/triceratops/image1.png'
),
loadingText: Text("Loading"),
photoSize: 110.0,
loaderColor: Colors.red,
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Flutter SplashScreen")
),
body: Center(
child:Text("Welcome to Home Page",
style: TextStyle( color: Colors.black, fontSize: 30)
)
),
);
}
}
上面的代码显示了应用程序的主屏幕最初是由SplashScreenPage
生成的,该对象的build()
方法返回一个SplashScreen
对象。seconds
参数指定显示启动画面的秒数。在指定时间用完之后,它将由HomeScreen(由navigationAfterSeconds
参数指定)替换。
4. 示例:基于时间+路由映射
如果应用程序使用路由映射导航页面,则可以在SplashScreen
之前放置SplashScreen
,如下图所示:
在这种情况下,navigationAfterSeconds
参数为String
类型,它是以要转到的页面命名。
参考下面示例代码:
import 'package:flutter/material.dart';
import 'package:splashscreen/splashscreen.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'yiibai.com',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: SplashScreenPage(),
routes: <String, WidgetBuilder>{
'/home': (BuildContext context) => HomePage(),
'/details': (BuildContext context) => DetailsPage(),
'/about': (BuildContext context) => AboutPage(),
},
);
}
}
class SplashScreenPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SplashScreen(
title: new Text('Welcome In SplashScreen' ),
image: new Image.network(
'https://s3.o7planning.com/images/triceratops/image1.png'
),
backgroundColor: Colors.white,
photoSize: 100.0,
loaderColor: Colors.red,
seconds: 15,
navigateAfterSeconds: "/home"
);
}
}
class HomePage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Title of Home Page"),
),
body: Center(
child: Row (
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
child: Text('Go to Details Page'),
onPressed: () {
Navigator.of(context).pushNamed('/details');
},
),
ElevatedButton(
child: Text('Go to About Page'),
onPressed: () {
Navigator.of(context).pushNamed('/about');
},
),
],
)
),
);
}
}
class DetailsPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Title of Details Page"),
),
body: Center(
child: ElevatedButton(
child: Text('Close'),
onPressed: () {
// Close page and pass a value back to previous page
Navigator.of(context).pop();
},
),
),
backgroundColor: Colors.lightGreen[100],
);
}
}
class AboutPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Title of About Page"),
),
body: Center(
child: ElevatedButton(
child: Text('Close'),
onPressed: () {
// Close page
Navigator.of(context).pop();
},
),
),
backgroundColor: Colors.cyan[100],
);
}
}
5. 示例:基于时间 + pageRoute
在Flutter中,通过使用“导航和路由”,可以从一页跳到另一页。这是从“启动画面”跳到主应用程序画面的一个比较好的做法。SplashScreen
类还必须支持Route
,这一点很重要。下面我们来看一个例子:
import 'package:flutter/material.dart';
import 'package:splashscreen/splashscreen.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'yiibai.com',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: SplashScreenPage()
);
}
}
class SplashScreenPage extends StatefulWidget {
@override
_SplashScreenPageState createState() => _SplashScreenPageState();
}
class _SplashScreenPageState extends State<SplashScreenPage> {
@override
Widget build(BuildContext context) {
return SplashScreen(
title: new Text('Welcome In SplashScreen'),
image: new Image.network(
'https://s3.o7planning.com/images/triceratops/image1.png'
),
backgroundColor: Colors.white,
photoSize: 100.0,
loaderColor: Colors.red,
seconds: 10,
navigateAfterSeconds: Text("Any Widget"), // Any not null widget.
pageRoute: _createRoute()
);
}
Route _createRoute() {
return PageRouteBuilder(
pageBuilder: (BuildContext context, Animation<double> animation,//
Animation<double> secondaryAnimation) {
return HomeScreen();
},
transitionsBuilder: (BuildContext context, Animation<double> animation, //
Animation<double> secondaryAnimation, Widget child) {
return child;
},
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Flutter SplashScreen")
),
body: Center(
child:Text("Welcome to Home Page",
style: TextStyle( color: Colors.black, fontSize: 30)
)
),
backgroundColor: Colors.green[100],
);
}
}
注意:在此示例中,需要设置seconds
,navigateAfterSeconds
和pageRoute
这几个参数。
- 如果不为
null
,将使用pageRoute
参数。 navigationAfterSeconds
参数是任何Widget
,而不是null
。即使不使用它,也必须为其设置一个值。
示例:
SplashScreen(
...
seconds: 10,
navigateAfterSeconds: Text("Any Widget"), // Any not null widget.
pageRoute: _createRoute()
);
6. 示例:Future基础
在某些情况下,“启动画面”用于指示应用程序准备就绪之前正在加载到内存中的状态。启动画面显示的时间长短取决于设备的情况。初始屏幕完成其任务后,它将被主应用程序屏幕替换。
从技术上讲,主屏幕将被包装在Future对象中,该对象可以在必要时替换SplashScreen
。
看看下面这个例子:
在此示例中,需要为navigationAfterFuture
参数设置一个值,而不是seconds
参数。
import 'package:flutter/material.dart';
import 'package:splashscreen/splashscreen.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'yiibai.com',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: SplashScreenPage()
);
}
}
class SplashScreenPage extends StatefulWidget {
@override
_SplashScreenPageState createState() => _SplashScreenPageState();
}
class _SplashScreenPageState extends State<SplashScreenPage> {
int loadingPercent = 0;
Future<Widget> loadFromFuture() async {
// <fetch data from server. ex. login>
while(this.loadingPercent < 100) {
this.setState(() {
this.loadingPercent++;
print("Percent: " + this.loadingPercent.toString());
});
// Delay 100 millisecond.
await Future.delayed(const Duration(milliseconds : 100));
}
// Show Main Screen (After Splash Screen)
return Future.value(HomeScreen());
}
@override
Widget build(BuildContext context) {
return SplashScreen(
navigateAfterFuture: loadFromFuture(),
title: Text(
'Welcome In SplashScreen',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0
),),
image: Image.network(
'https://s3.o7planning.com/images/triceratops/image1.png'
),
backgroundColor: Colors.white,
styleTextUnderTheLoader: TextStyle(),
photoSize: 100.0,
onClick: () => print("Flutter yiibai.com"),
loadingText: Text("Loading " + this.loadingPercent.toString() +" %"),
loaderColor: Colors.red
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter SplashScreen Package"),
automaticallyImplyLeading: false
),
body: Center(
child: Text(
"Welcome To Home Page!",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 30.0
),
),
),
);
}
}
7. Future基础 + 路由映射
接下来,我们将转到一个更复杂的示例。应用程序使用路线图导航页面,而SplashScreen
用来指示在应用程序准备使用之前,正在加载到内存中的应用程序的状态。
下面来看看效果:
示例代码如下:
import 'package:flutter/material.dart';
import 'package:splashscreen/splashscreen.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'yiibai.com',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: SplashScreenPage(),
routes: <String, WidgetBuilder>{
'/home': (BuildContext context) => HomePage(),
'/details': (BuildContext context) => DetailsPage(),
'/about': (BuildContext context) => AboutPage(),
},
);
}
}
class SplashScreenPage extends StatefulWidget {
@override
_SplashScreenPageState createState() => _SplashScreenPageState();
}
class _SplashScreenPageState extends State<SplashScreenPage> {
int loadingPercent = 0;
Future<String> loadFromFuture() async {
// <fetch data from server. ex. login>
while(this.loadingPercent < 100) {
this.setState(() {
this.loadingPercent++;
print("Percent: " + this.loadingPercent.toString());
});
// Delay 100 millisecond.
await Future.delayed(const Duration(milliseconds : 100));
}
// Show Main Screen (After Splash Screen)
return Future.value('/home');
}
@override
Widget build(BuildContext context) {
return SplashScreen(
navigateAfterFuture: loadFromFuture(),
title: Text(
'Welcome In SplashScreen',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0
),),
image: Image.network(
'https://s3.o7planning.com/images/triceratops/image1.png'
),
backgroundColor: Colors.white,
styleTextUnderTheLoader: TextStyle(),
photoSize: 100.0,
onClick: () => print("Flutter yiibai.com"),
loadingText: Text("Loading " + this.loadingPercent.toString() +" %"),
loaderColor: Colors.red
);
}
}
class HomePage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Title of Home Page"),
),
body: Center(
child: Row (
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
child: Text('Go to Details Page'),
onPressed: () {
Navigator.of(context).pushNamed('/details');
},
),
ElevatedButton(
child: Text('Go to About Page'),
onPressed: () {
Navigator.of(context).pushNamed('/about');
},
),
],
)
),
);
}
}
class DetailsPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Title of Details Page"),
),
body: Center(
child: ElevatedButton(
child: Text('Close'),
onPressed: () {
// Close page and pass a value back to previous page
Navigator.of(context).pop();
},
),
),
backgroundColor: Colors.lightGreen[100],
);
}
}
class AboutPage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Title of About Page"),
),
body: Center(
child: ElevatedButton(
child: Text('Close'),
onPressed: () {
// Close page
Navigator.of(context).pop();
},
),
),
backgroundColor: Colors.cyan[100],
);
}
}
8. loaderColor
loaderColor
属性用于设置指示应用程序加载进度的加载器(CircularProgressIndicator
)的颜色。
Color loaderColor