Flutter與Android的混合開發(3)Flutter如何跳轉到Activity,如何傳值

o動感超人o發表於2019-09-05
  1. 如何在現有Android專案裡嵌入Flutter Module
  2. Activity如何跳轉到Flutter頁面,如何傳值
  3. Flutter如何跳轉到Activity,如何傳值
  4. Android模組與Flutter模組的互動

全部原始碼已上傳github

Flutter跳轉Activity有2種方式:

  1. 通過Channel通知Android層跳轉
  2. 直接讓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,點選加入,大家一起學習討論

Flutter開發

相關文章