現有Android項目中集成Flutter/Flutter混合開發實戰(一)

最近學了下Flutter,確實挺好的。android

單獨的Flutter項目跑起來沒有多大問題。bash

目前也有一些混合開發的需求,因此找了一些文章來看,收穫頗豐。app

一.在現有項目上集成Flutter步驟詳解

1.建立項目

這一步要注意,建立項目的目錄,不是,不是,不是Android項目的根目錄ide


↑不是它!佈局

應該是下圖的目錄結構。flutter_hybrid目錄即爲咱們要建立的flutter項目,FlutterrHybridDemo是咱們現有的Android項目,叫什麼都好。能夠像我這樣,創建一個空文件夾,把現有Android項目拖進去,這樣方便查找和管理,否則flutter_hybrid會和FlutterHybridDemo平級,在一大堆項目中找這兩個也怪麻煩的。gradle


在這個目錄下打開cmd,執行命令:ui

flutter create -t module xxxx(想要建立的flutter項目名)執行完複製代碼

執行完後,一個和Android項目平級的flutter項目就已經建立好了。this

2.添加flutter到當前Android項目


在Android項目根目錄下的settings.gradle文件中,添加以下代碼:lua

setBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir.parentFile,
        "flutter_hybrid/.android/include_flutter.groovy"
))
複製代碼


而後,在項目的app目錄下,build.gradle文件中,添加以下dependency:spa

implementation project(':flutter')複製代碼


如上。添加完以後,準備工做就完成了。

二.集成Flutter

目前有兩種方式能夠添加

1.經過FlutterView方式添加到佈局中

首先經過Flutter.createFlutterView方法來建立一個FlutterView類型的View。它有三個構造參數。

public static FlutterView createView(Activity activity, Lifecycle lifecycle, String initialRoute)複製代碼

三個參數分別是:

1.Activity,即當前附着的Activity

2.LifeCycle,且是不能爲空(NonNull)的,這也就要求咱們必須用AppCompatActivity來承載FlutterView了,由於我試過了,若是咱們的Activity繼承自android.app.Activity是沒有getLifeCycle()這個方法的。

public class FlutterViewActivity extends AppCompatActivity 複製代碼

3.initialRoute

這是一個String類型的變量,能夠理解爲一個須要在Flutter中做爲身份標記的變量,根據不一樣的標識返回不一樣的Flutter頁面。

那麼在Flutter文件中咱們要這樣寫:


在 Flutter文件頁面中的build方法中,咱們能夠拿到window對象,經過window.defaultRouteName(就是咱們建立的時候傳遞的第三個參數)來區分返回不一樣界面

@override  Widget build(BuildContext context) {    switch(window.defaultRouteName){      case "flutter_view":        return _flutterHomeView(context);      default:        return Center(          child: Text('Unknown route: route', textDirection: TextDirection.ltr),        );
    }
}
Widget _flutterHomeView(context){    return Scaffold(      appBar: AppBar(title: Text('FlutterView的AppBar'),),      body: Center(        child: Text('如今是Flutter'),      ),    );  }
複製代碼

在當前Activity的OnCreate方法中,執行

setContentView(R.layout.activity_flutter);
FlutterView flutterView = Flutter.createView(this, getLifecycle(), "flutter_view");
layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
addContentView(flutterView, layoutParams);
複製代碼

因爲addContentView這個方法必需要傳遞一個LayoutParams參數,咱們就要用ViewGroup的LayoutParams。

這樣執行的結果是:


能夠看到Flutter頁面已經做爲一個View被添加到了Android原生界面中。這樣咱們就邁出了成功的第一步。

可是問題在於,咱們看到FlutterView仍然不是全屏的,Android的ActionBar和Flutter的AppBar疊了兩層額頭,很不舒服。

這種狀況,咱們能夠去掉二者任意一個。

好比在Android中,將當前Activity在AndroidManifest.xml文件中的theme屬性改一下

<activity android:name=".FlutterViewActivity" android:theme="@style/AppTheme.NoActionBar"></activity>複製代碼

那麼Activity的ActionBar就去掉了


不過,如今狀態欄不是沉浸式。關於這點,能夠用Android代碼在當前Activity中設置沉浸式狀態欄,網上有不少成熟的解決方式,在此筆者就不提供了。

不過僅僅這樣,我仍是不知足的。由於咱們的佈局中還有一個TextView控件,這時候怎麼沒了...

<RelativeLayotu
    android:id="@+id/rl_container"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/tv_native"
        android:textSize="50sp"
        android:text="原生文字控件"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>複製代碼

因此我要的效果是這樣的:


咱們都知道,若是使用了RelativeLayout或者FrameLayout的話,View默認addView是能夠重疊在一塊兒的。因此咱們的根佈局若是是RelativeLayotu的話,要設置LayoutParams,添加Rule規定FlutterView要處於控件的下方。

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_flutter);
    rlContainer = findViewById(R.id.rl_container);
    rlContainer.addView(flutterView)
    RelativeLayout.LayoutParams rlLayoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    rlLayoutParams.addRule(BELOW,R.id.tv_native);
    llContainer.addView(flutterView,rlLayoutParams);
複製代碼

不過我發現,addContentView()來添加的話, 即便是有LayoutParams也是會重疊在一塊兒的。因此個人建議是,使用最外層容器(或者是你要添加進的那個容器).addView來添加。

固然,經過LinearLayout來做爲容器,直接addView也是能夠的。

經過嘗試,發現只有addView的方式能夠達到這樣的效果。


不過這也足夠咱們開發中使用了。

未完待續...

相關文章
相關標籤/搜索