混合开发中不可避免的存在native向flutter页面跳转,flutter向原生跳转,甚至Activity或Fragment中某个view使用flutter开发。 咸鱼技术团队作为国内flutter技术领跑者开源了其混合栈的工具。 简书文章,或可以直接查阅GitHub仓库.
鉴于hyBirdStacManager中含有一些我们不很需要的功能和若干bug,目前我们可以借鉴下思路写个简单的工具类。
一、flutter -> native
flutter开启原生页面并传参较为简单,可以通过官方methodChannel直接调用native方法,不在赘述
dart代码
class MyFlutterPlugin {
static const MethodChannel _channel =
const MethodChannel('com.your.packagename/flutter_plugin');
/**
* 打开原生页面
*/
static Future openNativePage(String target , {Map paramsMap}) async {
if(paramsMap == null){
paramsMap = Map();
}
return await _channel.invokeMethod("openNative" , {"target" :target , "params" : paramsMap});
}
}
复制代码
参数的形式可以自定义为json,object等等
android端代码
注册插件的时机跟你的情况而定,现在先放在自动生成的插件后边
public abstract class BaseFlutterActivity extends FlutterFragmentActivity implements LifecycleOwner{
......
@Override
protected void onCreate(Bundle savedInstanceState) {
AppManager.getAppManager().addActivity(this);
......
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
//自定义plugin
MyPlugin.registerWith(getFlutterView());
}
}
public class MyPlugin {
public static void registerWith(final BinaryMessenger messenger){
new MethodChannel(messenger, "com.your.packagename/flutter_plugin").setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
....
// 解析参数,做页面跳转
if ("openNative".equals(methodCall.method)){
NativeRouteUtil.schemePage(methodCall,result);
}
}
});
}
}
跳转代码可参考伪代码
public static void schemePage(MethodCall methodCall, MethodChannel.Result result) {
String target = methodCall.argument("target");
switch (target) {
case FlutterConstant.ROUTE_NATIVE_SETTING:
SettingActivity.openSettingActivity(context);
break;
default:
break;
}
}
复制代码
二、native -> flutter
这是很容易想到的思路,为了保证界面跳转动画统一,页面栈方便维护(即使是flutter栈),在每次渲染一个新flutter页面的时候给他一个原生的载体,即一个Activity的壳,在Activity中的flutterView加载flutter页面
dart代码
flutter中有个main()方法入口,并且官方为我们提供了入口route的获取方式
void main(){
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.then((_){
runApp(new MyApp());
});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: _widgetForRoute(window.defaultRouteName),
);
}
}
Widget _widgetForRoute(String route) {
String uri = StringUtil.getSchemeRouteName(route);
String paramsJson = StringUtil.getSchemeRouteParams(route);
switch (uri) {
case ROUTE_ABOUT_US:
return AboutWidget(params: paramsJson);
default:
Toast.toast("您访问的页面不存在");
SystemNavigator.pop();
}
}
复制代码
_widgetForRoute(String route)方法的参数可以自行配置标准,可以为/path + ?+ params的形式,标记进入哪个页面和传递相应参数。
android端代码
套壳是常见的封装形式,举个简单的例子,
public class FlutterContainerActivity extends BaseFlutterActivity {
public static void openFlutterContainerAct(Context context, String url) {
try {
Intent intent = new Intent(context, FlutterContainerActivity.class);
intent.putExtra(ROUTE_TARGET,url);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.setAction(ROUTE_ACTION);
intent.addCategory(Intent.CATEGORY_DEFAULT);
context.startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
复制代码
三、native -> native
略.
不过可以封装一下,进入你的框架内,作为routeUtil的一部分
四、flutter -> flutter
虽然flutter内部有官方的跳转方法,但假如你的根flutter页面作为tab嵌入的方式渲染的话,如果用 Navigator.of(context)跳转,会发生新页面无法全屏的现象,所以还是为了动画统一和页面的良好管理机制,仍然推荐在dart内部先调用plugin方法,然后再用方式二进行跳转。
附dart内部的route跳转
class RouterUtil {
static const ROUTE = 1;
static const FADE = 2;
static route(BuildContext context, Widget targetWidget) {
Navigator.of(context)
.push(MaterialPageRoute(builder: (mContext) => targetWidget));
}
static routeAnimation(BuildContext context, Widget targetWidget) {
Navigator.of(context)
.push(_MyCustomRoute(builder: (context) => targetWidget));
}
static route4Animation(BuildContext context, Widget targetWidget , num type) {
Navigator.of(context)
.push(_MyCustomRoute(builder: (context) => targetWidget , type : type));
}
}
class _MyCustomRoute extends MaterialPageRoute {
num mType = 2;
_MyCustomRoute({WidgetBuilder builder, RouteSettings settings , var type})
: super(builder: builder, settings: settings);
@override
Widget buildTransitions(BuildContext context, Animation animation,
Animation secondaryAnimation, Widget child) {
if (settings.isInitialRoute) return child;
if(mType == 1){
return RotationTransition(turns: animation, child: child);
}else if(mType == 2){
return FadeTransition(opacity: animation, child: child);
}
return FadeTransition(opacity: animation, child: child);
}
}
复制代码
前两天闲鱼放弃了之前的混合栈项目,新开源了flutter_boost , 这是github,有兴趣可以参考。