Fluro
作為 一個Flutter
的 企業級的路由框架 ,確實不錯,可以解決多變的需求情況 ,是時候搞一波了。
我看了官方的demo
,寫的有點亂(反正我是這樣感覺的,老外的程式碼總是有點抽象),順便擴充套件一下傳參的問題和使用 Flutter
的 cupertino
轉場動畫。寫了一個demo
,
地址在:在這裡在這裡,快點我,快快快
本文基於 Fluro 目前版本 1.4.0 pub.dev/packages/fl…
1. 先看下Demo程式碼結構
2. 基礎使用
1. 導包
2. 基礎配置
1. application.dart
class Application {
static Router router;
}
複製程式碼
2. routes.dart
在routes.dart
檔案中配置路由,這裡需要注意的事首頁一定要用“/”配置
class Routes {
static String root = "/";
static String home = "/home";
static String demoParams = "/deme_params";
static String returnParams = "/return_params";
static String transitionDemo = "/transitionDemo";
static String transitionCustomDemo = "/transitionCustomDemo";
static String transitionCupertinoDemo = "/transitionCupertinoDemo";
static void configureRoutes(Router router) {
router.notFoundHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
print("ROUTE WAS NOT FOUND !!!");
});
/// 第一個引數是路由地址,第二個引數是頁面跳轉和傳參,第三個引數是預設的轉場動畫,可以看上圖
/// 我這邊先不設定預設的轉場動畫,轉場動畫在下面會講,可以在另外一個地方設定(可以看NavigatorUtil類)
router.define(root, handler: splashHandler);
router.define(home, handler: homeHandler);
router.define(demoParams, handler: demoParamHandler);
router.define(returnParams, handler: returnParamHandler);
router.define(transitionDemo, handler: transitionDemoHandler);
router.define(transitionCustomDemo, handler: transitionDemoHandler);
router.define(transitionCupertinoDemo, handler: transitionDemoHandler);
}
}
複製程式碼
3. main.dart
void main() {
// 註冊 fluro routes
Router router = Router();
Routes.configureRoutes(router);
Application.router = router;
runApp(MyApp());
}
複製程式碼
4. my_app.dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Weather App',
/// 生成路由
onGenerateRoute: Application.router.generator,
);
}
}
複製程式碼
3. 場景一:設定啟動頁 Splash 跳轉到 Home頁面,並且移除 Splash 頁面
只摘取相關程式碼,完整程式碼去 github
檢視,在文章最頂部
首先App啟動,先進入 首頁Splash 頁面,然後 倒數計時2秒,再進入home頁面
1. 效果圖
1. 首先先開啟 Splash 頁面
2. 兩秒後跳轉到 home 頁面
2. 程式碼
1. routes.dart
/// 這邊設定了首頁,固定寫法 /
static String root = "/";
/// home 頁面的 路由地址
static String home = "/home";
/// splashHandler 就是頁面跳轉,在route_handlers.dart
router.define(root, handler: splashHandler);
/// homeHandler home頁面
router.define(home, handler: homeHandler);
複製程式碼
2. route_handlers.dart
/// 跳轉到首頁Splash
var splashHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
return new SplashPag();
});
/// 跳轉到主頁
var homeHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
return HomePage();
});
複製程式碼
3. splash_page.dart
class SplashPag extends StatefulWidget {
@override
_SplashPagState createState() => _SplashPagState();
}
class _SplashPagState extends State<SplashPag> {
@override
void initState() {
// Future.delayed(Duration(seconds: 5),(){
// NavigatorUtil.goHomePage(context);
// });
/// 2秒後跳轉到主頁面,上面註釋的程式碼也可以做到倒數計時
Observable.timer(0, Duration(seconds: 2)).listen((_){
/// 然後看 NavigatorUtil.dart
NavigatorUtil.goHomePage(context);
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: Text('我是歡迎頁面'),
),
),
);
}
}
複製程式碼
4. NavigatorUtil.dart
/// 跳轉到主頁面
static void goHomePage(BuildContext context) {
/// Routes.home 路由地址
/// replace:true 就是將 splash 頁面給移除掉了,這點後退鍵的時候就不會再出現Splash頁面
Application.router.navigateTo(context, Routes.home, replace: true);
}
複製程式碼
5. home_page.dart
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
String name = "來自第一個介面測試一下";
int age = 14;
double score = 6.4;
bool sex = true;
Person person = new Person(name: 'Zeking', age: 18, sex: true);
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(child: Text('這是主頁')),
RaisedButton(
child: Text('傳遞引數string ,int,double,bool ,自定義型別'),
onPressed: () {
NavigatorUtil.goDemoParamsPage(
context, name, age, score, sex, person);
},
),
RaisedButton(
child: Text('傳遞引數,接受返回值'),
onPressed: () {
NavigatorUtil.goReturnParamsPage(context).then((result) {
debugPrint('${result.runtimeType}');
String message ;
/// 如果是 自定義的 Person 類
if (result.runtimeType == Person) {
message = result.toJson().toString();
debugPrint('${result.toJson().toString()}');
} else {
message = '$result';
debugPrint('$result');
}
showResultDialog(context, message);
});
},
),
RaisedButton(
child: Text('框架 自帶 轉場動畫 演示'),
onPressed: () {
NavigatorUtil.gotransitionDemoPage(context,
/// 這邊進行了 String 編碼
FluroConvertUtils.fluroCnParamsEncode("框架 自帶 轉場動畫 演示 \n\n\n "
"這邊只展示 inFromLeft ,剩下的自己去嘗試下,\n\n\n "
"架自帶的有 native,nativeModal,inFromLeft,inFromRight,inFromBottom,fadeIn,custom"));
},
),
RaisedButton(
child: Text('框架 自定義 轉場動畫 演示'),
onPressed: () {
NavigatorUtil.gotransitionCustomDemoPage(context,
FluroConvertUtils.fluroCnParamsEncode('框架 自定義 轉場動畫 演示'));
},
),
RaisedButton(
child: Text('修改原始碼,新增使用 Flutter 的 cupertino 轉場動畫'),
onPressed: () {
NavigatorUtil.gotransitionCupertinoDemoPage(
context,
FluroConvertUtils.fluroCnParamsEncode(
"修改原始碼,新增使用 Flutter 的 cupertino 轉場動畫"));
},
),
],
),
);
}
/// 顯示一個Dialgo
void showResultDialog(BuildContext context,String message){
showDialog(
context: context,
builder: (context) {
return new AlertDialog(
title: new Text(
"Hey Hey!",
style: new TextStyle(
color: const Color(0xFF00D6F7),
fontFamily: "Lazer84",
fontSize: 22.0,
),
),
content: new Text("$message"),
actions: <Widget>[
new Padding(
padding: new EdgeInsets.only(bottom: 8.0, right: 8.0),
child: new FlatButton(
onPressed: () {
Navigator.of(context).pop(true);
},
child: new Text("OK"),
),
),
],
);
},
);
}
}
複製程式碼
4. 場景二:傳參 String,int,double,bool,自定義型別
1. 效果圖
2. 程式碼
1. 注意點(型別轉換 fluro_convert_util.dart)
Fluro
路由地址,只能傳遞String
型別(並且不支援中文),所以需要對 中文,int
,double
,bool
,自定義型別進行一個轉換 , 寫了一個 轉換類 fluro_convert_util.dart
import 'dart:convert';
/// fluro 引數編碼解碼工具類
class FluroConvertUtils {
/// fluro 傳遞中文引數前,先轉換,fluro 不支援中文傳遞
static String fluroCnParamsEncode(String originalCn) {
return jsonEncode(Utf8Encoder().convert(originalCn));
}
/// fluro 傳遞後取出引數,解析
static String fluroCnParamsDecode(String encodeCn) {
var list = List<int>();
///字串解碼
jsonDecode(encodeCn).forEach(list.add);
String value = Utf8Decoder().convert(list);
return value;
}
/// string 轉為 int
static int string2int(String str) {
return int.parse(str);
}
/// string 轉為 double
static double string2double(String str) {
return double.parse(str);
}
/// string 轉為 bool
static bool string2bool(String str) {
if (str == 'true') {
return true;
} else {
return false;
}
}
/// object 轉為 string json
static String object2string<T>(T t) {
return fluroCnParamsEncode(jsonEncode(t));
}
/// string json 轉為 map
static Map<String, dynamic> string2map(String str) {
return json.decode(fluroCnParamsDecode(str));
}
}
複製程式碼
2. Person.dart 等下用到的自定義型別
class Person{
String name;
int age;
bool sex;
Person({this.name, this.age,this.sex});
Person.fromJson(Map<String, dynamic> json) {
name = json['name'];
age = json['age'];
sex = json['sex'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['age'] = this.age;
data['sex'] = this.sex;
return data;
}
}
複製程式碼
3. routes.dart
/// 配置路由地址 和 跳轉類和引數handler
static String demoParams = "/deme_params";
router.define(demoParams, handler: demoParamHandler);
複製程式碼
4. route_handlers.dart
/// 引數傳遞 int ,double,bool,自定義型別
var demoParamHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<Object>> params) {
/// params["name"]?.first 相當於 params["name"][0] ,打個debug 你就知道為什麼了是個list
String name = params["name"]?.first;
String age = params["age"]?.first;
String sex = params["sex"]?.first;
String score = params["score"]?.first;
String personjson = params['personjson']?.first;
/// 下面轉換為真實想要的型別
return DemoParamsPage(
name: name,
age: FluroConvertUtils.string2int(age),
score: FluroConvertUtils.string2double(score),
sex: FluroConvertUtils.string2bool(sex),
personJson: personjson,
);
});
複製程式碼
5. NavigatorUtil.dart
/// 跳轉到 傳參demo 頁面
static void goDemoParamsPage(BuildContext context, String name, int age,
double score, bool sex, Person person) {
/// 對中文進行編碼
String mName = FluroConvertUtils.fluroCnParamsEncode(name);
/// 對自定義型別 轉為 json string
String personJson = FluroConvertUtils.object2string(person);
Application.router.navigateTo(
context,
Routes.demoParams +
"?name=$name&age=$age&score=$score&sex=$sex&personjson=$personJson");
}
複製程式碼
6. home_page.dart 跳轉按鈕
String name = "來自第一個介面測試一下";
int age = 14;
double score = 6.4;
bool sex = true;
Person person = new Person(name: 'Zeking', age: 18, sex: true);
RaisedButton(
child: Text('傳遞引數string ,int,double,bool ,自定義型別'),
onPressed: () {
NavigatorUtil.goDemoParamsPage(
context, name, age, score, sex, person);
},
),
複製程式碼
7. demo_params_pag.dart
class DemoParamsPage extends StatefulWidget {
final String name;
final int age;
final double score;
final bool sex;
final String personJson;
DemoParamsPage({this.name, this.age, this.score, this.sex, this.personJson});
@override
_DemoParamsPageState createState() => _DemoParamsPageState();
}
class _DemoParamsPageState extends State<DemoParamsPage> {
@override
Widget build(BuildContext context) {
/// 對 中文 進行解碼
String mName = FluroConvertUtils.fluroCnParamsDecode(widget.name);
/// 對自定義類 進行解析
Person person =
Person.fromJson(FluroConvertUtils.string2map(widget.personJson));
print(person.name);
print(person.age);
print(person.sex);
/// 下面的寫法也可以
Map<String, dynamic> data = FluroConvertUtils.string2map(widget.personJson);
print(data["name"]);
print(data["age"]);
print(data["sex"]);
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('name:$mName'),
Text('age:${widget.age}'),
Text('score:${widget.score}'),
Text('sex:${widget.sex}'),
Text('Person:${person.toJson().toString()}'),
RaisedButton(
child: Text('返回'),
onPressed: () {
NavigatorUtil.goBack(context);
},
)
],
),
),
);
}
}
複製程式碼
5. 場景三:接收返回值 String,int,double,自定義型別
1. 效果圖
2. routes.dart
static String returnParams = "/return_params";
router.define(returnParams, handler: returnParamHandler);
複製程式碼
3. route_handlers.dart
/// 關閉頁面,返回引數
var returnParamHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<Object>> params) {
return ReturnParamsPage();
});
複製程式碼
4. NavigatorUtil.dart
/// 跳轉到 會返回引數的 頁面
static Future goReturnParamsPage(BuildContext context) {
return Application.router.navigateTo(context, Routes.returnParams);
}
複製程式碼
5. home_page.dart
RaisedButton(
child: Text('傳遞引數,接受返回值'),
onPressed: () {
NavigatorUtil.goReturnParamsPage(context).then((result) {
debugPrint('${result.runtimeType}');
String message ;
/// 如果是 自定義的 Person 類
if (result.runtimeType == Person) {
message = result.toJson().toString();
debugPrint('${result.toJson().toString()}');
} else {
message = '$result';
debugPrint('$result');
}
showResultDialog(context, message);
});
},
)
/// 顯示一個Dialgo
void showResultDialog(BuildContext context,String message){
showDialog(
context: context,
builder: (context) {
return new AlertDialog(
title: new Text(
"Hey Hey!",
style: new TextStyle(
color: const Color(0xFF00D6F7),
fontFamily: "Lazer84",
fontSize: 22.0,
),
),
content: new Text("$message"),
actions: <Widget>[
new Padding(
padding: new EdgeInsets.only(bottom: 8.0, right: 8.0),
child: new FlatButton(
onPressed: () {
Navigator.of(context).pop(true);
},
child: new Text("OK"),
),
),
],
);
},
);
}
複製程式碼
6. return_params_page.dart
class ReturnParamsPage extends StatefulWidget {
@override
_ReturnParamsPageState createState() => _ReturnParamsPageState();
}
class _ReturnParamsPageState extends State<ReturnParamsPage> {
@override
Widget build(BuildContext context) {
Person person = new Person(name: "returnName", age: 23, sex: false);
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: RaisedButton(
child: Text('返回,並且返回string'),
onPressed: () {
NavigatorUtil.goBackWithParams(context, "我是返回值哦");
},
),
),
RaisedButton(
child: Text('返回,並且返回int'),
onPressed: () {
NavigatorUtil.goBackWithParams(context, 12);
},
),
RaisedButton(
child: Text('返回,並且返回double'),
onPressed: () {
NavigatorUtil.goBackWithParams(context, 3.1415926);
},
),
RaisedButton(
child: Text('返回,並且返回bool'),
onPressed: () {
NavigatorUtil.goBackWithParams(context, true);
},
),
RaisedButton(
child: Text('返回,並且返回自定義型別'),
onPressed: () {
NavigatorUtil.goBackWithParams(context, person);
},
)
],
),
);
}
}
複製程式碼
6. 場景四:使用 框架 自帶 的 轉場動畫
1. 效果圖
2. routes.dart
static String transitionDemo = "/transitionDemo";
router.define(transitionDemo, handler: transitionDemoHandler);
複製程式碼
3. route_handlers.dart
/// 轉場動畫 頁面
var transitionDemoHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<Object>> params) {
String title = params["title"]?.first;
return TransitionDemoPage(title);
});
複製程式碼
4. NavigatorUtil.dart
/// 跳轉到 轉場動畫 頁面 , 這邊只展示 inFromLeft ,剩下的自己去嘗試下,
/// 框架自帶的有 native,nativeModal,inFromLeft,inFromRight,inFromBottom,fadeIn,custom
static Future gotransitionDemoPage(BuildContext context, String title) {
return Application.router.navigateTo(
context, Routes.transitionDemo + "?title=$title",
/// 指定了 轉場動畫 inFromLeft
transition: TransitionType.inFromLeft);
}
複製程式碼
5. home_page.dart
RaisedButton(
child: Text('框架 自帶 轉場動畫 演示'),
onPressed: () {
NavigatorUtil.gotransitionDemoPage(context,
/// 這邊進行了 String 編碼
FluroConvertUtils.fluroCnParamsEncode("框架 自帶 轉場動畫 演示 \n\n\n "
"這邊只展示 inFromLeft ,剩下的自己去嘗試下,\n\n\n "
"架自帶的有 native,nativeModal,inFromLeft,inFromRight,inFromBottom,fadeIn,custom"));
},
),
複製程式碼
6. transition_demo_page.dart
場景五 ,場景六 ,用到一樣的 transition_demo_page 後面就不展示了
class TransitionDemoPage extends StatefulWidget {
final String title;
TransitionDemoPage(this.title);
@override
_TransitionDemoPageState createState() => _TransitionDemoPageState();
}
class _TransitionDemoPageState extends State<TransitionDemoPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Text(
/// string 解碼
FluroConvertUtils.fluroCnParamsDecode(widget.title),
textAlign: TextAlign.center,
)),
RaisedButton(
child: Text('返回'),
onPressed: () {
NavigatorUtil.goBack(context);
},
)
],
),
);
}
}
複製程式碼
7. 場景五:自定義轉場動畫
1. 效果圖
2. routes.dart
static String transitionCustomDemo = "/transitionCustomDemo";
router.define(transitionCustomDemo, handler: transitionDemoHandler);
複製程式碼
3. route_handlers.dart
/// 轉場動畫 頁面
var transitionDemoHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<Object>> params) {
String title = params["title"]?.first;
return TransitionDemoPage(title);
});
複製程式碼
4. NavigatorUtil.dart
/// 自定義 轉場動畫
static Future gotransitionCustomDemoPage(BuildContext context, String title) {
var transition = (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return new ScaleTransition(
scale: animation,
child: new RotationTransition(
turns: animation,
child: child,
),
);
};
return Application.router.navigateTo(
context, Routes.transitionCustomDemo + "?title=$title",
transition: TransitionType.custom, /// 指定是自定義動畫
transitionBuilder: transition, /// 自定義的動畫
transitionDuration: const Duration(milliseconds: 600)); /// 時間
}
複製程式碼
5. home_page.dart
RaisedButton(
child: Text('框架 自定義 轉場動畫 演示'),
onPressed: () {
NavigatorUtil.gotransitionCustomDemoPage(context,
FluroConvertUtils.fluroCnParamsEncode('框架 自定義 轉場動畫 演示'));
},
),
複製程式碼
8. 場景六:修改原始碼,新增使用 Flutter 的 cupertino 轉場動畫
1. 檢視原始碼,為什麼沒有 Flutter 的 cupertino
看下圖,發現它自帶的 轉場動畫 只有 這幾個,沒有我喜歡的Flutter
的cupertino
轉場動畫,側滑關閉頁面,
繼續看原始碼 ,看下圖,最後也是呼叫了系統的MaterialPageRoute
和 PageRouteBuilder
2. 修改原始碼
看下圖,自己新增 cupertino
型別
CupertinoPageRoute
3. 效果圖
4. routes.dart
static String transitionCupertinoDemo = "/transitionCupertinoDemo";
router.define(transitionCupertinoDemo, handler: transitionDemoHandler);
複製程式碼
5. route_handlers.dart
/// 轉場動畫 頁面
var transitionDemoHandler = new Handler(
handlerFunc: (BuildContext context, Map<String, List<Object>> params) {
String title = params["title"]?.first;
return TransitionDemoPage(title);
})
複製程式碼
6. NavigatorUtil.dart
/// 使用 IOS 的 Cupertino 的轉場動畫,這個是修改了原始碼的 轉場動畫
/// Fluro本身不帶,但是 Flutter自帶
static Future gotransitionCupertinoDemoPage(
BuildContext context, String title) {
return Application.router.navigateTo(
context, Routes.transitionCupertinoDemo + "?title=$title",
transition: TransitionType.cupertino);
}
複製程式碼
7. home_page.dart
RaisedButton(
child: Text('修改原始碼,新增使用 Flutter 的 cupertino 轉場動畫'),
onPressed: () {
NavigatorUtil.gotransitionCupertinoDemoPage(
context,
FluroConvertUtils.fluroCnParamsEncode(
"修改原始碼,新增使用 Flutter 的 cupertino 轉場動畫"));
},
複製程式碼
掃一掃,關注我的微信公眾號
都是一些個人學習筆記
點選下面閱讀原文,用電腦看,有目錄,更舒服哦