- 如何在現有Android專案裡嵌入Flutter Module
- Activity如何跳轉到Flutter頁面,如何傳值
- Flutter如何跳轉到Activity,如何傳值
- Android模組與Flutter模組的互動
全部原始碼已上傳github
Flutter跳轉Activity有2種方式:
- 通過Channel通知Android層跳轉
- 直接讓Flutter頁面嵌入Android的View
Flutter如何跳轉到Activity,如何傳值
我們修改一下之前的MainActivity,增加我們這次的示例程式碼
Android程式碼
MainActivity.kt
package com.liuhc.myapplication
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import io.flutter.view.FlutterMain
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.startActivity
/**
* 描述:首頁
* 作者:liuhc
* 建立日期:2019-09-05 on 11:21 AM
*/
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//強烈建議放到Application裡初始化,初始化一次即可,放這裡只是舉個例子
FlutterMain.startInitialization(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//addContentView方式新增FlutterView
page1.setOnClickListener {
startActivity<Page1Activity>()
}
//普通Fragment方式新增FlutterView
page2.setOnClickListener {
startActivity<Page2Activity>()
}
//使用FlutterFragmentActivity
page3.setOnClickListener {
startActivity<PageFlutterFragmentActivity>()
}
//使用FlutterActivity
page4.setOnClickListener {
startActivity<PageFlutterActivity>()
}
//addContentView方式新增FlutterView並傳遞引數
page1Param.setOnClickListener {
startActivity<Page1ParamActivity>()
}
//解決debug模式下黑屏的另一種方式
noBlack.setOnClickListener {
startActivity<DebugNoBlackActivity>()
}
//進入Flutter頁面演示通過Channel跳轉到Activity
jumpByChannel.setOnClickListener {
startActivity<JumpActivityFlutterWidget>()
}
//進入嵌入了Android平臺的View的Flutter頁面
insertAndroidView.setOnClickListener {
startActivity<InsertAndroidViewFlutterWidget>()
}
}
}
複製程式碼
JumpActivityFlutterWidget.kt
package com.liuhc.myapplication
import android.os.Bundle
import io.flutter.app.FlutterActivity
import io.flutter.plugin.common.MethodChannel
import io.flutter.view.FlutterMain
import org.jetbrains.anko.startActivity
/**
* 描述:這個頁面包含FlutterView,然後點選FlutterView中的按鈕跳轉到另一個Activity,
* 這種方式其實只是呼叫Channel通訊而已
*
* 作者:liuhc
* 建立日期:2019-09-04 on 23:30
*/
class JumpActivityFlutterWidget : FlutterActivity() {
private lateinit var methodChannel: MethodChannel
override fun onCreate(savedInstanceState: Bundle?) {
//強烈建議放到Application裡初始化,初始化一次即可,放這裡只是舉個例子
FlutterMain.startInitialization(this)
//intent的引數設定必須在super.onCreate之前,因為super.onCreate裡會取這些引數
intent.action = "android.intent.action.RUN"
intent.putExtra("route", "page4")
super.onCreate(savedInstanceState)
initMethodChannel()
//呼叫super.onCreate(savedInstanceState)之後flutterView才有值,
//所以如果需要註冊外掛,則應該放到super.onCreate(savedInstanceState)程式碼之後才可以
flutterView.enableTransparentBackground()
}
//Flutter跳轉Activity的方式1,使用Channel
private fun initMethodChannel() {
methodChannel = MethodChannel(
this.registrarFor("pluginKeyMainActivity").messenger(),
"MainActivityMethodChannel"
)
methodChannel.setMethodCallHandler { methodCall, result ->
if (methodCall.method == "jumpTestActivity") {
startActivity<TestActivity>()
}
}
}
}
複製程式碼
TestActivity.kt
package com.liuhc.myapplication
import android.annotation.SuppressLint
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.LinearLayout
import android.widget.TextView
/**
* 描述:
* 作者:liuhc
* 建立日期:2019-09-05 on 14:31
*/
class TestActivity : AppCompatActivity() {
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val linearLayout = LinearLayout(this)
val layoutParam = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
val textView = TextView(this)
textView.text = "TestActivity:我被跳轉過來了"
val viewParam = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
linearLayout.addView(textView, viewParam)
setContentView(linearLayout, layoutParam)
}
}
複製程式碼
InsertAndroidViewFlutterWidget.kt
package com.liuhc.myapplication
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import io.flutter.view.FlutterMain
import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.startActivity
/**
* 描述:首頁
* 作者:liuhc
* 建立日期:2019-09-05 on 11:21 AM
*/
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
//強烈建議放到Application裡初始化,初始化一次即可,放這裡只是舉個例子
FlutterMain.startInitialization(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//addContentView方式新增FlutterView
page1.setOnClickListener {
startActivity<Page1Activity>()
}
//普通Fragment方式新增FlutterView
page2.setOnClickListener {
startActivity<Page2Activity>()
}
//使用FlutterFragmentActivity
page3.setOnClickListener {
startActivity<PageFlutterFragmentActivity>()
}
//使用FlutterActivity
page4.setOnClickListener {
startActivity<PageFlutterActivity>()
}
//addContentView方式新增FlutterView並傳遞引數
page1Param.setOnClickListener {
startActivity<Page1ParamActivity>()
}
//解決debug模式下黑屏的另一種方式
noBlack.setOnClickListener {
startActivity<DebugNoBlackActivity>()
}
//進入Flutter頁面演示通過Channel跳轉到Activity
jumpByChannel.setOnClickListener {
startActivity<JumpActivityFlutterWidget>()
}
//進入嵌入了Android平臺的View的Flutter頁面
insertAndroidView.setOnClickListener {
startActivity<InsertAndroidViewFlutterWidget>()
}
}
}
複製程式碼
Dart程式碼
main.dart
import 'dart:convert';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'insert_android_view_page.dart';
import 'invoke_method_page.dart';
import 'jump_activity_page.dart';
import 'my_home_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
//方式1
home: _getWidgetByRoute(window.defaultRouteName),
//方式2 如果route相同,優先匹配routes而不是home
routes: <String, WidgetBuilder>{
"page1": (context) => MyHomePage(
title: "匹配到了page1",
message: "通過routes變數",
),
"page2": (context) => MyHomePage(
title: "匹配到了page2",
message: "通過routes變數",
),
"page3": (context) => MyHomePage(
title: "匹配到了page3",
message: "通過routes變數",
),
"page4": (context) => JumpActivityPage(),
"page5": (context) => InsertAndroidViewPage(),
},
//當通過routes和home的返回值都為null的話,才會從onUnknownRoute尋找
onUnknownRoute: (RouteSettings settings) {
return new PageRouteBuilder(pageBuilder: (BuildContext context, _, __) {
//這裡為返回的Widget
return MyHomePage(
title: "沒有匹配到",
message: "通過onUnknownRoute變數",
);
});
},
);
}
}
//如果要接收平臺層傳送的引數,除了使用Channel以外(這種方式不是正常的方式,強烈不推薦),就只能通過window.defaultRouteName了,
//因為routes的route只能提前定義好,無法動態判斷
Widget _getWidgetByRoute(String jsonStr) {
print("json=$jsonStr");
String _route;
Map<String, dynamic> jsonMap;
try {
jsonMap = json.decode(jsonStr);
_route = jsonMap["path"];
} catch (e) {
print(e);
_route = jsonStr;
}
switch (_route) {
//接收到了匹配的規則,跳轉到flutter指定頁面
case 'page1':
return MyHomePage(
title: "匹配到了page1",
message: "通過home變數",
);
case 'page1Param':
return MyHomePage(
title: "匹配到了page1Param",
message: jsonMap["param"],
);
case "InvokeMethodPage":
return InvokeMethodPage(
title: jsonMap["title"],
channelName: jsonMap["channelName"],
androidMethod: jsonMap["androidMethod"],
);
default:
return MyHomePage(
title: "沒有匹配到",
message: "通過home變數",
);
}
}
複製程式碼
jump_activity_page.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class JumpActivityPage extends StatefulWidget {
@override
_JumpActivityPageState createState() => _JumpActivityPageState();
}
class _JumpActivityPageState extends State<JumpActivityPage> {
MethodChannel _methodChannel;
@override
void initState() {
_methodChannel = MethodChannel("MainActivityMethodChannel");
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("我是Flutter頁面"),
),
body: RaisedButton(
child: Text("點我通過傳送Channel訊息通知Android層跳轉頁面"),
onPressed: (){
_methodChannel.invokeMethod("jumpTestActivity");
},
),
);
}
}
複製程式碼
insert_android_view_page.dart
import 'dart:io' show Platform;
import 'package:flutter/material.dart';
/// 描述:嵌入AndroidView
/// 作者:liuhc
/// 建立日期:2019-09-05 on 3:20 PM
class InsertAndroidViewPage extends StatefulWidget {
@override
_InsertAndroidViewPageState createState() => _InsertAndroidViewPageState();
}
class _InsertAndroidViewPageState extends State<InsertAndroidViewPage> {
GlobalKey key = GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("我來演示如何嵌入AndroidView"),
),
body: Platform.isAndroid ? AndroidView(key: key, viewType: 'InsertAndroidView') : Text("ios和Android實現原理一樣"));
}
}
複製程式碼
歡迎加入Flutter開發群457664582,點選加入,大家一起學習討論