【Flutter 混合开发】添加 Flutter 到 Android Fragment
Flutter 混合开发系列 包含如下:
- 嵌入原生View-Android
- 嵌入原生View-iOS
- 与原生通信-MethodChannel
- 与原生通信-BasicMessageChannel
- 与原生通信-EventChannel
- 添加 Flutter 到 Android Activity
- 添加 Flutter 到 Android Fragment
- 添加 Flutter 到 iOS
每个工作日分享一篇,欢迎关注、点赞及转发。
使用新引擎创建 FlutterFragment
添加 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 布局文件修改如下:
<?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 原生的知识。
上面已经加载了 UI,但并不能一些交互和行为,通常情况下,需要将 Activity 的生命周期透传给 FlutterFragment:
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
上面的方式每一个 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 的渲染模式
FlutterFragment 的渲染模式有两种:SurfaceView 和 TextureView,默认是 SurfaceView,SurfaceView 的性能比 TextureView 好,但其层次结构必须在最顶层或最底层,而且在 Android N之前的Android版本上,无法对 SurfaceView 进行动画处理,因为它们的布局和渲染与其他 View 层次结构不同步,因此要合理选择渲染模式,渲染模式设置方法如下:
val fragment = FlutterFragment
.withNewEngine()
.renderMode(RenderMode.texture)
.build<FlutterFragment>()
设置 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】:
![]() |
![]() |
【Flutter 混合开发】添加 Flutter 到 Android Fragment的更多相关文章
- 【Flutter 混合开发】添加 Flutter 到 Android Activity
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
- Flutter混合开发:Android接入Flutter
Flutter Google推出已经已经一年多了,单个 Flutter 项目的开发流程已经很成熟了.对与个人开发者来说使用 Flutter 开发一个跨平台的App挺有意思.但是对于现有的项目改造来说还 ...
- 【Flutter 混合开发】添加 Flutter 到 iOS
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
- 【Flutter 混合开发】嵌入原生View-Android
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-IOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
- 【Flutter 混合开发】嵌入原生View-iOS
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
- 【Flutter 混合开发】与原生通信-MethodChannel
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
- 【Flutter 混合开发】与原生通信-BasicMessageChannel
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
- 【Flutter 混合开发】与原生通信-EventChannel
Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...
- flutter 混合开发
flutter 混合开发 https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps https://flutter.de ...
随机推荐
- iOS14 debug安装的带有flutter应用从桌面图标重新启动时闪退
刚刚升级遇到的问题,希望能够帮助到遇到相同问题的人. 用xcode12连接iOS设备调试安装应用 拔掉数据线 从桌面图标点击进入App必闪退 后来发现是flutter的原因,目前有下面两种个解决方案: ...
- Cypress系列(60)- 运行时的截图和录屏
如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 背景 在测试运行时截图和录屏能够在测试错 ...
- React 服务端渲染方案完美的解决方案
最近在开发一个服务端渲染工具,通过一篇小文大致介绍下服务端渲染,和服务端渲染的方式方法.在此文后面有两中服务端渲染方式的构思,根据你对服务端渲染的利弊权衡,你会选择哪一种服务端渲染方式呢? 什么是服务 ...
- Effective C++ 读书笔记 名博客
https://www.cnblogs.com/harlanc/tag/effective%20c%2B%2B/default.html?page=3
- 解决Dubbo无法发布被事务代理的Service问题
在HelloServiceImpl类上加入@Transactional注解后,虽然工程可以正常跑起来,但是通过dubbo管理控制台可以看到里面并没有服务发布上来. 此时启动服务提供者和服务消费者,并访 ...
- Python单向链表的实现
链表由一系列不必在内存中相连的结构构成,这些对象按线性顺序排序.每个结构含有表元素和指向后继元素的指针.最后一个单元的指针指向NULL.为了方便链表的删除与插入操作,可以为链表添加一个表头. 删除操作 ...
- HTML CSS+JS想要做放大镜练习,如何获取同样的大图和小图?
1.进入某商城找到对应的图片: 步骤一: 步骤二: 步骤三: 2.检查源代码: 情况一:按F12 情况二:鼠标在网页内,直接右键-->"检查元素" 1.选中选择部分 2.点击 ...
- kubernetes-介绍与特性
1. kubernetes概述 1) kubernetes是什么 2) kubernetes能做什么 3) kubernetes特性 4) kubernetes集群架构与组件 5) kubernete ...
- TTL电平,CMOS电平,232/485电平,OC门,OD门基础知识
1.RS232电平 或者说串口电平,有的甚至说计算机电平,所有的这些说法,指得都是计算机9针串口 (RS232)的电平,采用负逻辑, -15v ~ -3v 代表1 +3v ~ +15v 代表0 2. ...
- [Docker] redis 全配置
启动容器,加载配置文件并持久化数据 docker run -d --privileged=true -p 6379:6379 --restart always -v /usr/redis/conf:/ ...