Flutter 混合開發系列 包含以下:android
- 嵌入原生View-Android
- 嵌入原生View-iOS
- 與原生通訊-MethodChannel
- 與原生通訊-BasicMessageChannel
- 與原生通訊-EventChannel
- 添加 Flutter 到 Android Activity
- 添加 Flutter 到 Android Fragment
- 添加 Flutter 到 iOS
每一個工做日分享一篇,歡迎關注、點贊及轉發。git
添加 Flutter 到 Fragment 與添加 Activity 基本同樣,若是添加到 Activity 知足需求,建議使用 Activity,由於 Activity 更加靈活和易於使用。緩存
添加到 Fragment 代碼:微信
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val fragment = FlutterFragment.createDefault() supportFragmentManager .beginTransaction() .add(R.id.fragment_container, fragment) .commit() } }
activity_main 佈局文件修改以下:app
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <FrameLayout android:id="@+id/fragment_container" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toTopOf="@+id/button"/> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="跳轉" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
紅色區域就是 FlutterFragment 部分,這裏大部分是 Android 原生的知識。less
上面已經加載了 UI,但並不能一些交互和行爲,一般狀況下,須要將 Activity 的生命週期透傳給 FlutterFragment:ide
class MainActivity : AppCompatActivity() { override fun onPostResume() { super.onPostResume() flutterFragment!!.onPostResume() } override fun onNewIntent(@NonNull intent: Intent) { flutterFragment!!.onNewIntent(intent) } override fun onBackPressed() { flutterFragment!!.onBackPressed() } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String?>, grantResults: IntArray ) { flutterFragment!!.onRequestPermissionsResult( requestCode, permissions, grantResults ) } override fun onUserLeaveHint() { flutterFragment!!.onUserLeaveHint() } override fun onTrimMemory(level: Int) { super.onTrimMemory(level) flutterFragment!!.onTrimMemory(level) } }
指定引擎路由:函數
val fragment = FlutterFragment .withNewEngine() .initialRoute("one_page") .build<FlutterFragment>() supportFragmentManager .beginTransaction() .add(R.id.fragment_container, fragment) .commit()
上面的方式每個 FlutterFragment 都會建立一個 FlutterEngine(Flutter 引擎),固然 FlutterFragment 也支持 緩存引擎,用法與 Activity 同樣,在 MyApplication 啓動引擎:佈局
class MyApplication : Application() { lateinit var flutterEngine: FlutterEngine override fun onCreate() { super.onCreate() flutterEngine = FlutterEngine(this) flutterEngine.dartExecutor.executeDartEntrypoint( DartExecutor.DartEntrypoint.createDefault() ) FlutterEngineCache .getInstance() .put("engine_id", flutterEngine) } }
使用:性能
val fragment = FlutterFragment .withCachedEngine("engine_id") .build<FlutterFragment>() supportFragmentManager .beginTransaction() .add(R.id.fragment_container, fragment) .commit()
初始化緩存引擎的路由:
flutterEngine = FlutterEngine(this) flutterEngine.navigationChannel.setInitialRoute("one_page") flutterEngine.dartExecutor.executeDartEntrypoint( DartExecutor.DartEntrypoint.createDefault() ) FlutterEngineCache .getInstance() .put("engine_id", flutterEngine)
默認狀況下,FlutterFragment 的 entrypoint(入口點)是 main() 函數,咱們能夠修改其 entrypoint,
val fragment = FlutterFragment .withNewEngine() .dartEntrypoint("newMain") .build<FlutterFragment>()
在 main.dart 文件中添加 entrypoint(入口點):
void main() => runApp(MyApp()); void newMain()=> runApp(NewApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), routes: { 'one_page':(context){ return OnePage(); }, 'two_page':(context){ return TwoPage(); } }, home: MyHomePage(title: 'Flutter Demo Home Page'), ); } } class NewApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: TwoPage() ); } }
newMain 即新的 entrypoint。
FlutterFragment 的渲染模式有兩種:SurfaceView 和 TextureView,默認是 SurfaceView,SurfaceView 的性能比 TextureView 好,但其層次結構必須在最頂層或最底層,並且在 Android N以前的Android版本上,沒法對 SurfaceView 進行動畫處理,由於它們的佈局和渲染與其餘 View 層次結構不一樣步,所以要合理選擇渲染模式,渲染模式設置方法以下:
val fragment = FlutterFragment .withNewEngine() .renderMode(RenderMode.texture) .build<FlutterFragment>()
默認狀況下,FlutterFragment 使用 SurfaceView 渲染不透明背景。對於Flutter未繪製的任何像素,背景均爲黑色。因爲性能緣由,首選使用不透明背景進行渲染。 Android上具備透明的 Flutter 渲染會對性能產生負面影響。可是,有的時候須要其透明,顯示其底下的 UI,所以,Flutter在 FlutterFragment 中支持設置爲透明。
val fragment = FlutterFragment .withNewEngine() .transparencyMode(TransparencyMode.transparent) .build<FlutterFragment>()
將按下放置在 FlutterFragment 的底下,
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="跳轉" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"/> <FrameLayout android:id="@+id/fragment_container" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
此時 FlutterFragment 的背景已經透明瞭,但運行時發現並無透明,按鈕也沒有顯示,這是由於 Flutter 自己沒有設置透明,設置Flutter 透明:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), backgroundColor: Colors.transparent, ... ); }
老孟Flutter博客(330個控件用法+實戰入門系列文章):http://laomengit.com
歡迎加入Flutter交流羣(微信:laomengit)、關注公衆號【老孟Flutter】:
![]() |
![]() |