【Flutter 混合开发】添加 Flutter 到 Android Fragment
<p><img src="https://img2020.cnblogs.com/other/467322/202010/467322-20201029221809283-1917315759.png"></p><blockquote>
<p>Flutter 混合开发系列 包含如下:</p>
<ul>
<li>嵌入原生View-Android</li>
<li>嵌入原生View-iOS</li>
<li>与原生通信-MethodChannel</li>
<li>与原生通信-BasicMessageChannel</li>
<li>与原生通信-EventChannel</li>
<li>添加 Flutter 到 Android Activity</li>
<li><strong>添加 Flutter 到 Android Fragment</strong></li>
<li>添加 Flutter 到 iOS</li>
</ul>
<p>每个工作日分享一篇,欢迎关注、点赞及转发。</p>
</blockquote>
<h4 id="使用新引擎创建-flutterfragment">使用新引擎创建 FlutterFragment</h4>
<p>添加 Flutter 到 Fragment 与添加 Activity 基本一样,如果添加到 Activity 满足需求,建议使用 Activity,因为 Activity 更加灵活和易于使用。</p>
<p>添加到 Fragment 代码:</p>
<pre><code class="language-kotlin">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()
}
}
</code></pre>
<p><strong>activity_main</strong> 布局文件修改如下:</p>
<pre><code><?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>
</code></pre>
<p><img src="https://img2020.cnblogs.com/other/467322/202010/467322-20201029221809766-1616375736.png"></p>
<p>红色区域就是 FlutterFragment 部分,这里大部分是 Android 原生的知识。</p>
<p>上面已经加载了 UI,但并不能一些交互和行为,通常情况下,需要将 Activity 的生命周期透传给 FlutterFragment:</p>
<pre><code class="language-kotlin">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)
}
}
</code></pre>
<h4 id="初始化新引擎路由">初始化新引擎路由</h4>
<p>指定引擎路由:</p>
<pre><code class="language-kotlin">val fragment = FlutterFragment
.withNewEngine()
.initialRoute("one_page")
.build<FlutterFragment>()
supportFragmentManager
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit()
</code></pre>
<p><img src="https://img2020.cnblogs.com/other/467322/202010/467322-20201029221809986-1710071019.png"></p>
<h4 id="使用缓存引擎创建-flutterfragment">使用缓存引擎创建 FlutterFragment</h4>
<p>上面的方式每一个 FlutterFragment 都会创建一个 FlutterEngine(Flutter 引擎),当然 FlutterFragment 也支持 缓存引擎,用法与 Activity 一样,在 MyApplication 启动引擎:</p>
<pre><code class="language-kotlin">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)
}
}
</code></pre>
<p>使用:</p>
<pre><code class="language-kotlin">val fragment = FlutterFragment
.withCachedEngine("engine_id")
.build<FlutterFragment>()
supportFragmentManager
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit()
</code></pre>
<h4 id="初始化缓存引擎路由">初始化缓存引擎路由</h4>
<p>初始化缓存引擎的路由:</p>
<pre><code class="language-kotlin">flutterEngine = FlutterEngine(this)
flutterEngine.navigationChannel.setInitialRoute("one_page")
flutterEngine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
FlutterEngineCache
.getInstance()
.put("engine_id", flutterEngine)
</code></pre>
<p><img src="https://img2020.cnblogs.com/other/467322/202010/467322-20201029221810212-888979431.png"></p>
<h4 id="更改入门点">更改入门点</h4>
<p>默认情况下,FlutterFragment 的 entrypoint(入口点)是<strong>main()</strong> 函数,我们可以修改其 entrypoint,</p>
<pre><code class="language-kotlin">val fragment = FlutterFragment
.withNewEngine()
.dartEntrypoint("newMain")
.build<FlutterFragment>()
</code></pre>
<p>在 <strong>main.dart</strong> 文件中添加 entrypoint(入口点):</p>
<pre><code class="language-dart">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()
);
}
}
</code></pre>
<p><strong>newMain</strong> 即新的 entrypoint。</p>
<p><img src="https://img2020.cnblogs.com/other/467322/202010/467322-20201029221810375-2046780715.png"></p>
<h4 id="更改-flutterfragment-的渲染模式">更改 FlutterFragment 的渲染模式</h4>
<p>FlutterFragment 的渲染模式有两种:SurfaceView 和 TextureView,默认是 SurfaceView,SurfaceView 的性能比 TextureView 好,但其层次结构必须在最顶层或最底层,而且在 Android N之前的Android版本上,无法对 SurfaceView 进行动画处理,因为它们的布局和渲染与其他 View 层次结构不同步,因此要合理选择渲染模式,渲染模式设置方法如下:</p>
<pre><code class="language-kotlin">val fragment = FlutterFragment
.withNewEngine()
.renderMode(RenderMode.texture)
.build<FlutterFragment>()
</code></pre>
<h4 id="设置-flutterfragment-透明">设置 FlutterFragment 透明</h4>
<p>默认情况下,FlutterFragment 使用 SurfaceView 渲染不透明背景。对于Flutter未绘制的任何像素,背景均为黑色。由于性能原因,首选使用不透明背景进行渲染。 Android上具有透明的 Flutter 渲染会对性能产生负面影响。但是,有的时候需要其透明,显示其底下的 UI,因此,Flutter在 FlutterFragment 中支持设置为透明。</p>
<pre><code class="language-kotlin">val fragment = FlutterFragment
.withNewEngine()
.transparencyMode(TransparencyMode.transparent)
.build<FlutterFragment>()
</code></pre>
<p>将按下放置在 FlutterFragment 的底下,</p>
<pre><code><?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>
</code></pre>
<p>此时 FlutterFragment 的背景已经透明了,但运行时发现并没有透明,按钮也没有显示,这是因为 Flutter 本身没有设置透明,设置Flutter 透明:</p>
<pre><code class="language-dart">@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
backgroundColor: Colors.transparent,
...
);
}
</code></pre>
<p><img src="https://img2020.cnblogs.com/other/467322/202010/467322-20201029221810502-324834400.png"></p>
<h2 id="交流">交流</h2>
<p>老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com</p>
<p>欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><img src="https://img2020.cnblogs.com/other/467322/202010/467322-20201029221811398-985169561.png"></td>
<td><img src="https://img2020.cnblogs.com/other/467322/202010/467322-20201029221811866-797659790.png"></td>
</tr>
</tbody>
</table><br><br>
来源:https://www.cnblogs.com/mengqd/p/13899607.html
頁:
[1]