上一篇已介绍Flutter和Android混合开发的环境搭配,这篇简单介绍下如何从Flutter界面跳转到原生Android开发界面,进行数据交互。
一、Flutter之间的简单页面跳转
第一步:Flutter工程在pubspec.yaml文件中导入包:fluro: ^1.4.0,导入之后点击Pub get。
第二步:创建RouterUtils.dart(很多人的命名是Application.dart,我这边的命名是:RouterUtils.dart),代码如下
class RouterUtils { static FluroRouter router; }
第三步:创建Routers.dart,代码如下:
class Routers { static GlobalKey<NavigatorState> navigatorKey = GlobalKey(); static void configureRoutes(FluroRouter router) { router.notFoundHandler = Handler(handlerFunc: (BuildContext context, Map<String, List<String>> parameters) { /// 页面找不到了,跳转到404界面 return PageNotFound(); }); /// 根据路由设置的名称找到对应的界面 router.define(RouterName.root, handler: RouterHandler.indexHandle); router.define(RouterName.first, handler: RouterHandler.firstHandler); router.define(RouterName.second, handler: RouterHandler.secondeHandler); } }
第四步:创建一个专名路由命名的RouterName.dart,代码如下:
class RouterName { static String root = '/'; // 这是在MainActivity显示的对应界面 static String first = '/first'; static String second = '/second'; }
第五步:创建一个跳转Flutter界面的RouterHandler.dart,代码如下:
class RouterHandler { static var indexHandle = new Handler(handlerFunc: (context, parameters) { return IndexPage(); // 这是你要跳转的Flutter界面,需要在lib中创建该类 }, );
static var firstHandler = new Handler(handlerFunc: (context, parameters) { return FirstPage(parameters["title"].first); // 跳转界面传一个值 } ); static var secondeHandler = new Handler(handlerFunc: (context, parameters) { var map = { "id": parameters['id'].first, "title": parameters['title'].first, }; return SecondPage(map); // 跳转界面传多个值 } ); }
第六步:创建navigator_util.dart,进行Flutter界面之间的跳转,代码如下:
class NavigatorUtil { /// 路由跳转界面 static push(BuildContext context, String path, {bool replace = false, bool clearStack = false,TransitionType transition=TransitionType.cupertino}) { FocusScope.of(context).unfocus(); RouterUtils.router.navigateTo(context, path, replace: replace, clearStack: clearStack, transition: transition); } }
点击跳转代码:
NavigatorUtil.push(context, "${RouterName.first}?title=Hello");//传一个参数 其中 title 和上面parameters['title']必须是同一个参数 NavigatorUtil.push(context, "${RouterName.second }?id=1&title=Hello"); //传多个参数,用&分开
第七步:在main.dart中初始化,代码如下(显示的布局是RouterName.root对应的Flutter)
void main() async { FluroRouter router = FluroRouter(); Routers.configureRoutes(router); RouterUtils.router = router; runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter 混合开发', navigatorKey: Routers.navigatorKey, onGenerateRoute: RouterUtils.router.generator, theme: ThemeData( primarySwatch: Colors.green, ), ); } }
二、Flutter简单跳转到Activity界面:
第一步:创建method_channel_utils.dart,代码如下
class MethodChannelUtils{ /// Flutter跳转到Activity界面的KEY static const platformChannel = const MethodChannel('song.test.com.myapplication'); }
第二步:跳转到Activity原生代码界面,代码如下):
Flutter跳转代码:
InkWell( onTap: () async { Map resultMap = Map(); resultMap['name'] = "winner"; resultMap['age'] = "26"; resultMap['sex'] = "男"; // 其中first对应Activity里面的key(下面会介绍),resultMap是两个界面需要传送的参数 await MethodChannelUtils.platformChannel.invokeMethod('first', resultMap); }, child: Text('跳转到Activity中'), ),
MainActivity接受代码(代码接着上一期的MainActivity后面添加就行了):
// FLUTTER_NAME对应上面Flutter中MethodChannelUtils中的platformChannel值('song.test.com.myapplication') 如:FLUTTER_NAME = 'song.test.com.myapplication' MethodChannel methodChannel = new MethodChannel(TestApp.getApp().getFlutterEngine().getDartExecutor(), FLUTTER_NAME); methodChannel.setMethodCallHandler((call, result) -> { Log.i("111111", "call: " + call.method); switch (call.method) { case "first": // 对应Flutter传过来的Key Map<String, String> map = (Map<String, String>) call.arguments; // 获取Flutter传过来的值 UserEntity entity = new UserEntity(); entity.setName(map.get("name")); entity.setAge(map.get("age")); entity.setSex(map.get("sex")); startActivity(new Intent(FirstActivity.this, SecondActivity.class).putExtra("entity", entity)); break; } });
注意:以下代码需要在MainActivity.java添加,也就是显示Flutter界面的时候添加,避免点击系统返回键出现异常(这是其中一个代表)
@Override public void onBackPressed() { if (this.mFlutterFragment != null) { this.mFlutterFragment.onBackPressed(); } else { super.onBackPressed(); } }