Fluro
作为 一个Flutter
的 企业级的路由框架 ,确实不错,可以解决多变的需求情况 ,是时候搞一波了。 我看了官方的demo
,写的有点乱(反正我是这样感觉的,老外的代码总是有点抽象),顺便扩展一下传参的问题和使用 Flutter
的 cupertino
转场动画。写了一个demo
, 地址在:
本文基于 Fluro 目前版本 1.4.0
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> 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.dartrouter.define(root, handler: splashHandler);/// homeHandler home页面router.define(home, handler: homeHandler);复制代码
2. route_handlers.dart
/// 跳转到首页Splash var splashHandler = new Handler( handlerFunc: (BuildContext context, Map> params) { return new SplashPag();});/// 跳转到主页var homeHandler = new Handler( handlerFunc: (BuildContext context, Map > params) { return HomePage();});复制代码
3. splash_page.dart
class SplashPag extends StatefulWidget { @override _SplashPagState createState() => _SplashPagState();}class _SplashPagState extends State{ @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{ @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: [ 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: [ 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 (); ///字符串解码 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) { return fluroCnParamsEncode(jsonEncode(t)); } /// string json 转为 map static Map 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(Mapjson) { name = json['name']; age = json['age']; sex = json['sex']; } Map toJson() { final Map data = new Map (); data['name'] = this.name; data['age'] = this.age; data['sex'] = this.sex; return data; }}复制代码
3. routes.dart
/// 配置路由地址 和 跳转类和参数handlerstatic String demoParams = "/deme_params";router.define(demoParams, handler: demoParamHandler);复制代码
4. route_handlers.dart
/// 参数传递 int ,double,bool,自定义类型var demoParamHandler = new Handler( handlerFunc: (BuildContext context, Map> 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{ @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 data = FluroConvertUtils.string2map(widget.personJson); print(data["name"]); print(data["age"]); print(data["sex"]); return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ 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> 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:[ 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{ @override Widget build(BuildContext context) { Person person = new Person(name: "returnName", age: 23, sex: false); return Scaffold( body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ 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> 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{ @override Widget build(BuildContext context) { return Scaffold( body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ 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> params) { String title = params["title"]?.first; return TransitionDemoPage(title);});复制代码
4. NavigatorUtil.dart
/// 自定义 转场动画 static Future gotransitionCustomDemoPage(BuildContext context, String title) { var transition = (BuildContext context, Animationanimation, Animation 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> 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 转场动画")); },复制代码
参考
扫一扫,关注我的微信公众号
都是一些个人学习笔记
点击下面阅读原文,用电脑看,有目录,更舒服哦