Mục lục
- SplashScreen là gì?
- Thư viện SplashScreen
- Example: Time based
- Example: Time based + route Map
- Example: Time based + pageRoute
- Example: Time based + routeName
- Example: Future based
- Example: Future based + route Map
- loaderColor
- navigateAfterFuture
- seconds
- pageRoute
- onClick
- navigateAfterSeconds
- title
- backgroundColor
- styleTextUnderTheLoader
- image
- photoSize
- loadingText
- useLoader
- imageBackground
- gradientBackground
- routeName
Hướng dẫn và ví dụ Flutter SplashScreen
Xem thêm các chuyên mục:
- SplashScreen là gì?
- Thư viện SplashScreen
- Example: Time based
- Example: Time based + route Map
- Example: Time based + pageRoute
- Example: Time based + routeName
- Example: Future based
- Example: Future based + route Map
- loaderColor
- navigateAfterFuture
- seconds
- pageRoute
- onClick
- navigateAfterSeconds
- title
- backgroundColor
- styleTextUnderTheLoader
- image
- photoSize
- loadingText
- useLoader
- imageBackground
- gradientBackground
- routeName

Là một website được viết trên công nghệ web Flutter vì vậy hỗ trợ rất tốt cho người học, kể cả những người học khó tính nhất.
Hiện tại website đang tiếp tục được cập nhập nội dung cho phong phú và đầy đủ hơn. Mong các bạn nghé thăm và ủng hộ website mới của chúng tôi.


Splash Screen là màn hình người dùng nhìn thấy đầu tiên khi môt ứng dụng được khởi chạy. Nó cũng có thể là màn hình chào mừng của ứng dụng cung cấp trải nghiệm ban đầu đơn giản khi một trò chơi hoặc chương trình di động đang khởi chạy. Đôi khi Splash Screen được sử dụng để cho người dùng xem trạng thái ứng dụng đang được tải lên bộ nhớ trước khi nó sẵn sàng hoạt động.

Sau đây là các đặc điểm cơ bản của Splash Screen:
- Nó chủ yếu được sử dụng để xây dựng thương hiệu hoặc nhận dạng danh tính của ứng dụng và tạo ấn tượng thương hiệu cho người dùng.
- Nó cũng được sử dụng để hiển thị tiến trình ứng dụng được tải lên bộ nhớ để trình bầy phần mềm cho người dùng.
- Khi tải xong Splash Screen, người dùng sẽ nhận được một màn hình chức năng khác sẽ là màn hình chính hoặc trang tổng quan (dashboard), sau đó nó sẽ bị lãng quên. Khi quá trình tải hoàn tất, chúng ta không thể nhấn nút quay lại để quay lại Splash Screen.
Trong bài viết này tôi sẽ hướng dẫn bạn sử dụng thư viện splashscreen được cung cấp bởi cộng đồng, nó không sẵn có trong thư viện tiêu chuẩn của Flutter vì vậy để sử dụng bạn phải khai báo nó trong project.
Trên project, mở file pubspec.yaml và khai báo thư viện splashscreen:
pubspec.yaml
.....
dependencies:
flutter:
sdk: flutter
splashscreen: ^1.3.5

Bạn có thể tìm thấy các phiên bản khác hoặc mới nhất của thư viện splashscreen tại liên kết dưới đây:
Lớp SplashScreen cung cấp 3 constructor:
SplashScreen Constructor
@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 Constructor
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 Constructor
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}
)
Bố cục của SplashScreen:

Trước hết chúng ta sẽ bắt đầu với một ví dụ đơn giản, một Splash Screen hiển thị trong một khoảng thời gian được chỉ định, sau đó nó sẽ được thay thế bởi màn hình chính của ứng dụng. Hãy xem trước kết quả của ví dụ:

Trước hết, bạn cần tạo một dự án Flutter và khai báo thư viện splashscreen vào dự án của bạn như đã được đề cập ở phía trên.
Tiếp theo, mở file main.dart và thay thế nó nội dung của nó bởi code dưới đây:
main.dart (ex1)
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('o7planning.org',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)
)
),
);
}
}
Code ở trên cho thấy rằng ban đầu màn hình chính của ứng dụng được tạo ra bởi SplashScreenPage, phương thức build() của lớp này trả về một đối tượng SplashScreen.
Tham số seconds chỉ định số giây Splash Screen sẽ hiển thị, sau khi hết thời gian nó sẽ được thay thế bởi HomeScreen (Được chỉ định bởi tham số navigateAfterSeconds).

Nếu ứng dụng của bạn sử dụng route Map để điều hướng các trang bạn có thể đặt SplashScreen ở phía trước giống như hình minh hoạ dưới đây:

Trong tình huống này tham số navigateAfterSeconds là kiểu String, nó là tên của một trang mà bạn muốn chuyển hướng đến.

main.dart (ex2)
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: 'o7planning.org',
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],
);
}
}
Trong Flutter sử dụng Navigator & Route bạn có thể nhẩy từ một trang này sang một trang khác, và đây chính là một ý tưởng để bạn chuyển từ Splash Screen tới màn hình chính của ứng dụng. Điều quan trọng là lớp SplashScreen cũng hỗ trợ Route, chúng ta hãy xem một ví dụ:
main.dart (ex3)
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: 'o7planning.org',
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],
);
}
}
Chú ý: Trong ví dụ này bạn cần sét đặt giá trị cho các tham số seconds, navigateAfterSeconds và pageRoute.
- Tham số pageRoute sẽ được sử dụng nếu nó không null.
- Tham số navigateAfterSeconds là một Widget bất kỳ và không null, mặc dù nó không được sử dụng nhưng bạn cần phải sét đặt giá trị cho nó.
SplashScreen(
...
seconds: 10,
navigateAfterSeconds: Text("Any Widget"), // Any not null widget.
pageRoute: _createRoute()
);
- TODO
Trong một số tình huống Splash Screen được sử dụng để biểu thị trạng thái ứng dụng đang được tải vào bộ nhớ trước khi ứng dụng sẵn sàng sử dụng đối với người dùng. Khoảng thời gian mà Splash Screen hiển thị phụ thuộc vào sức mạnh của thiết bị. Sau khi Splash Screen hoàn thành các nhiệm vụ, nó sẽ được thay thế bởi màn hình chính của ứng dụng.
Về mặt kỹ thuật màn hình chính sẽ được gói trong một đối tượng Future (Tương lai) để sẵn sàng thay thế Splash Screen khi cần thiết.
Hãy xem trước ví dụ này:

Trong ví dụ này bạn cần sét đặt giá trị cho tham số navigateAfterFuture và không sét đặt giá trị cho tham số seconds.
main.dart (ex7)
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: 'o7planning.org',
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 o7planning.org"),
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
),
),
),
);
}
}
Tiếp theo chúng ta sẽ đến với một ví dụ phức tạp hơn, ứng dụng của bạn sử dụng route Map để điều hướng các trang, và SplashScreen được sử dụng để biểu thị trạng thái ứng dụng đang được tải vào bộ nhớ trước khi ứng dụng sẵn sàng sử dụng đối với người dùng.

Xem trước ví dụ:

main.dart (ex8)
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: 'o7planning.org',
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 o7planning.org"),
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],
);
}
}
Property loaderColor được sử dụng để sét đặt mầu sắc của loader (CircularProgressIndicator) đang biểu thị tiến trình tải của ứng dụng.
Color loaderColor

Future navigateAfterFuture
Xem giải thích về property này trong ví dụ ở trên.
Property seconds được sử dụng để sét đặt số giây Splash Screen sẽ xuất hiện trước khi nó được thay thế bởi màn hình chính của ứng dụng.
int seconds
Nếu bạn sét đặt giá trị cho tham số seconds có nghĩa là bạn chọn cách điều hướng dựa trên thời gian, sau khi thời gian hết hạn Splash Screen sẽ được thay thế bởi màn hình chính của ứng dụng.
Route pageRoute
Xem giải thích về property này trong ví dụ ở trên.
dynamic onClick
dynamic navigateAfterSeconds
Xem giải thích về property này trong ví dụ ở trên.
title là một widget nằm phía dưới image, trong hầu hết các trường hợp sử dụng nó là một đối tượng Text.
Text title: const Text('')

Property backgroundColor được sử dụng để sét đặt mầu nền cho Splash Screen, giá trị mặc định của nó là Colors.white.
Color backgroundColor: Colors.white
Property styleTextUnderTheLoader không còn được sử dụng.
TextStyle styleTextUnderTheLoader:
const TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold, color: Colors.black)
Property image được sử dụng để chỉ định một ảnh xuất hiện trong Splash Screen, nó được đặt trong một CircleAvatar với bán kính là photoSize.
Image image

- TODO Link?
Về mặt cấu trúc image của SplashScreen được đặt trong một CircleAvatar và photoSize là giá trị của bán kính.

double photoSize
loadingText là một widget nằm ở phía dưới của loader (CircularProgressIndicator) thường được sử dụng để hiển thị thông tin liên quan tới tiến trình tải của ứng dụng.
Text loadingText: const Text("")
Property useLoader được sử dụng để hiển thị (hoặc không hiển thị) loader (CircularProgressIndicator) trên SplashScreen. Mặc định nó có giá trị true, nghĩa là loader sẽ được hiển thị.
bool useLoader: true
imageBackground được sử dụng để sét đặt hình nền cho SplashScreen.
ImageProvider<Object> imageBackground
- TODO Link?
Gradient gradientBackground
- TODO Link?
String routeName
Xem giải thích về property này trong ví dụ ở trên.