混合開發中不可避免的存在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<String> 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<T> extends MaterialPageRoute<T> {
num mType = 2;
_MyCustomRoute({WidgetBuilder builder, RouteSettings settings , var type})
: super(builder: builder, settings: settings);
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> 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,有興趣可以參考。