1. 程式人生 > 其它 >ios開發 自定義btn_Flutter 混合開發

ios開發 自定義btn_Flutter 混合開發

技術標籤:ios開發 自定義btn

目前大多數公司都有自己開發多年的專案,不可能直接用Flutter從頭開發一套,那樣不實現,除非是小專案,因此只能是在原有的基礎上用Flutter來開發新業務或重構舊業務,而這裡就需要用到Flutter混合開發

一、建立Flutter模組

使用混合開發就不能像之前一樣直接上來就建立一個Flutter專案,而是要使用Flutter模板

12345
# flutter_module_lxf 可以隨便你命名flutter create --template module flutter_module_lxf# --template 可以替換為 -t# flutter create -t module flutter_module_lxf

創建出來的Flutter模組依然是可以像之前建立的Flutter專案一樣開啟和執行的。

目錄下有也有iosandroid目錄,只不過前面加了個點 ,成了點目錄。

二、iOS

整合

通過Cocoapods,將Flutter模組編譯成一個庫,再到原生專案中進行引入和使用即可

Podfile中新增兩行配置

12345
# 指定我們剛剛建立的 Flutter 模組的路徑flutter_application_path = '../flutter_module_lxf'# 拼接指令碼檔案的路徑: .ios/Flutter/podhelper.rbload File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

在每個需要引用FlutterTarget下,都需要新增一行配置

1
install_all_flutter_pods(flutter_application_path)

新增後如下所示:

123456789
flutter_application_path = '../flutter_module_lxf'load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')use_frameworks!target 'LXFFlutterHybridDemo' do    install_all_flutter_pods(flutter_application_path)  end

新增完成後,執行一次pod install

混合開發混合開發

使用

兩個步驟

  1. 獲取 Flutter引擎FlutterEngine

  2. 通過FlutterEngine建立FlutterViewController

基本使用

AppDelegate類中宣告一個FlutterEngine變數,在didFinishLaunchingWithOptions方法中啟動Flutter引擎

1234567891011121314151617181920
// AppDelegate.swiftimport [email protected] AppDelegate: UIResponder, UIApplicationDelegate {      // 建立 Flutter引擎    lazy var flutterEngine = FlutterEngine(name: "lxf")    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {                // 啟動 Flutter引擎        flutterEngine.run()                return true    }    ...}

ViewController中新增一個按鈕,點選彈出Flutter模組

1234567891011121314151617181920212223
// ViewController.swiftoverride func viewDidLoad() {  super.viewDidLoad()  let btn = UIButton(type: .custom)  btn.frame = CGRect(x: 100, y: 200, width: 200, height: 44)  btn.backgroundColor = .black  btn.addTarget(self, action: #selector(showFlutterVc), for: .touchUpInside)  btn.setTitle("彈出Flutter模組", for: .normal)  self.view.addSubview(btn)}@objc func showFlutterVc() {  // 建立FlutterViewController  let flutterVc = FlutterViewController(engine: fetchFlutterEngine(), nibName: nil, bundle: nil)  self.present(flutterVc, animated: true, completion: nil)}func fetchFlutterEngine() -> FlutterEngine {  return (UIApplication.shared.delegate as! AppDelegate).flutterEngine}

如果遇到報Command PhaseScriptExecution failed with a nonzero exit code錯誤,如下圖所示:

請先用Android StudioVSCode開啟Flutter模組專案並執行到iOS裝置上,讓其幫我們對iOS專案進行一些初始化配置。成功執行後就可以關閉Flutter模組專案的運行了,接著再用Xcode開啟原生專案執行即可。

修改初始路由

官方文件裡面提到,修改初始路由,需要在Flutter引擎run之前,通過invokeMethod呼叫setInitialRoute方法進行設定,程式碼如下

1234
// 修改初始路由flutterEngine.navigationChannel.invokeMethod("setInitialRoute", arguments: "/other")// 啟動 Flutter引擎flutterEngine.run()

但是,我發現這樣寫並沒有起任何作用,在Flutter的官方issue上也有人提到這個問題,目前只能官方進行修復和調整API

【setInitialRoute is broken for iOS add-to-app #59895】: https://github.com/flutter/flutter/issues/59895

臨時可以使用如下方式實現:

123
let flutterVc = FlutterViewController(project: FlutterDartProject(), nibName: nil, bundle: nil)flutterVc.setInitialRoute("/other")self.present(flutterVc, animated: true, completion: nil)

雖然這麼寫可以實現這個功能,但是會有明顯的類似卡頓的現象,因為使用這種方式去建立FlutterViewController之前,會隱式建立和啟動一個FlutterEngine,而我們彈出FlutterViewControllerFlutterEngine還沒載入完畢,所以我們會看到先彈出了一個透明的介面,再顯示/other路由對應的介面檢視。

使用 FlutterAppDelegate

使用FlutterAppDelegate這個不是必要的操作,但是如果你想讓Flutter模組也能使用原生的功能的話,建議使用

原生功能

  • 處理openURL的回撥

  • 列表檢視在點選狀態列後滾到頂部

1
class AppDelegate: FlutterAppDelegate

更具體的使用,請閱讀官方文件

https://flutter.dev/docs/development/add-to-app/ios/add-flutter-screen?tab=no-engine-vc-swift-tab#using-the-flutterappdelegate

三、Android

修改安卓專案 根目錄下的settings.gradle檔案

123456789
// settings.gradleinclude ':app'                                    // assumed existing contentsetBinding(new Binding([gradle: this]))                                // newevaluate(new File(                                                     // new  settingsDir.parentFile,                                              // new  // 這裡的 flutter_module_lxf 請修改為你自己建立的Flutter模板目錄名稱  'flutter_module_lxf/.android/include_flutter.groovy'                 // new))

修改安卓專案app目錄下的build.gradle檔案

1234567
// app/build.gradledependencies {  ...  // 配置flutter依賴  implementation project(':flutter')}

如果在編譯的時候遇到如下錯誤

1
Default interface methods are only supported starting with Android N (--min-api 24): void androidx.lifecycle.DefaultLifecycleObserver.onCreate(androidx.lifecycle.LifecycleOwner)

請確認是否指定了使用Java 8進行編譯【官方文件 - Java 8 requirement】

https://flutter.dev/docs/development/add-to-app/android/project-setup#java-8-requirement

修改安卓專案app目錄下的build.gradle檔案

12345678910
// app/build.gradleandroid {	...  compileOptions {      sourceCompatibility 1.8      targetCompatibility 1.8  }  ...}

修改app/src/main/AndroidManifest.xml檔案

123456789
// app/src/main/AndroidManifest.xml<activity  android:name="io.flutter.embedding.android.FlutterActivity"  android:theme="@style/AppTheme"  android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"  android:hardwareAccelerated="true"  android:windowSoftInputMode="adjustResize"  />

新增一個按鈕,點選彈出Flutter模組

12345678910111213
<Button    android:id="@+id/btn"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:textSize="20sp"    android:text="彈出Flutter模組"    android:background="#000000"    android:textColor="#ffffff"    android:gravity="center"    android:onClick="btnClick"    />
1234567
// MainActivity.javapublic void btnClick(View v) {    startActivity(        FlutterActivity.createDefaultIntent(this)    );}

四、除錯與熱過載

由於當前我們是使用原生開發工具(如:Xcode)來執行專案,每次修改我們的Flutter模組的程式碼,也就需要重新執行才能看到效果,不像之前按下Cmd + s就能進行熱過載。這樣Flutter模組的開發效率極其低下,那有沒有辦法可以讓我們像之前開發Flutter專案時那樣進行熱過載呢?答案是有的

Flutter官方提供了flutter attach,以輔助我們開發,到終端下執行

1
flutter attach

如果當前有多個裝置,會提示我們需要指定attach哪個裝置

按要求加上指定引數即可

1
flutter attach -d FE305309-9E79-418D-BA3F-7EFECF2980BC

如圖,這樣就關聯上了,你在dart檔案裡面對介面進行任何修改後,按r進行熱過載,按R進行熱啟動。

如果你使用的是Android Studio,可以直接選擇對應的裝置後,點選右邊的Flutter Attach按鈕,執行成功後就可以跟之前一樣按Cmd + s進行熱過載了。

五、資料

  • GitHub

    LXFFlutterHybridDemo

https://github.com/LinXunFeng/LXFFlutterHybridDemo

官方文件

add-to-app

https://flutter.dev/docs/development/add-to-app

add-to-app/ios

https://flutter.dev/docs/development/add-to-app/ios

add-to-app/android

https://flutter.dev/docs/development/add-to-app/android

Debugging & hot reload

https://flutter.dev/docs/development/add-to-app/debugging