FlutterActivity完全覆盖视图,原生BottomNavigationBar不显示如何解决?
我尝试创建一个可显示Flutter模块同时展示原生Android BottomNavigationBar的FlutterActivity,但Flutter模块及UI完全覆盖了Activity视图,导致BottomNavigationBar无法显示。请问有没有解决办法?
相关代码
启动Flutter模块的Kotlin函数
fun startFlutterModule(context: Context, action: String? = null) { val methodChannel = getMethodChannel(context) val cfid = recoverCfid() val map = mutableMapOf( "difc" to cfid, "application" to environmentSelected ) if (action != null) { map["action"] = action } methodChannel.invokeMethod("showFlutterModule", map) context.startActivity(FlutterActivity .withCachedEngine("for_start_engine") .build(context)) hasFlutterActivityRunning = true }
AndroidManifest配置
<activity android:name="io.flutter.embedding.android.FlutterActivity" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"/>
依赖配置
debugImplementation 'com.valemobi.flut.integration_agora_flutter:flutter_debug:1.0' profileImplementation 'com.valemobi.flut.integration_agora_flutter:flutter_profile:1.0' releaseImplementation 'com.valemobi.flut.integration_agora_flutter:flutter_release:1.0'
默认的FlutterActivity会将FlutterView设置为整个Activity的内容视图,自然会覆盖原生的BottomNavigationBar。要实现两者共存,需要把FlutterView嵌入到原生布局中,以下是两种可行方案:
方案一:自定义FlutterActivity,嵌入FlutterView到原生布局
创建包含BottomNavigationBar的原生布局
新建activity_flutter_with_bottom_nav.xml布局文件,将Flutter内容区域和底部导航栏垂直排列:<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!-- Flutter内容容器,占满剩余空间 --> <FrameLayout android:id="@+id/flutter_container" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <!-- 原生底部导航栏 --> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_nav" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:attr/windowBackground" app:menu="@menu/bottom_nav_menu" /> </LinearLayout>注意:需要提前创建对应的底部菜单文件
res/menu/bottom_nav_menu.xml。实现自定义FlutterActivity
继承FlutterActivity,在onCreate中加载自定义布局,将FlutterView添加到布局容器中:class FlutterWithBottomNavActivity : FlutterActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_flutter_with_bottom_nav) // 获取或初始化缓存的FlutterEngine val flutterEngine = FlutterEngineCache.getInstance().get("for_start_engine") ?: FlutterEngine(this).apply { dartExecutor.executeDartEntrypoint( DartExecutor.DartEntrypoint.createDefault() ) FlutterEngineCache.getInstance().put("for_start_engine", this) } // 创建FlutterView并关联到引擎,添加到容器 val flutterView = FlutterView(this).apply { attachToFlutterEngine(flutterEngine) } findViewById<FrameLayout>(R.id.flutter_container).addView(flutterView) // 配置底部导航栏的点击事件,可通过MethodChannel通知Flutter切换页面 findViewById<BottomNavigationView>(R.id.bottom_nav).setOnItemSelectedListener { item -> val methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "nav_channel") methodChannel.invokeMethod("navigateTo", item.title.toString()) true } // 传递初始化参数给Flutter val methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "init_channel") val cfid = recoverCfid() val map = mutableMapOf( "difc" to cfid, "application" to environmentSelected ) intent.getStringExtra("action")?.let { map["action"] = it } methodChannel.invokeMethod("showFlutterModule", map) } }注册自定义Activity到AndroidManifest
替换原来的FlutterActivity配置,或者新增这个自定义Activity的注册:<activity android:name=".FlutterWithBottomNavActivity" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"/>修改启动函数
启动自定义的Activity而非默认的FlutterActivity:fun startFlutterModule(context: Context, action: String? = null) { val intent = Intent(context, FlutterWithBottomNavActivity::class.java) action?.let { intent.putExtra("action", it) } context.startActivity(intent) hasFlutterActivityRunning = true }
方案二:使用FlutterFragment嵌入到原生Activity
如果你的原生页面已经有BottomNavigationBar,也可以将Flutter内容以FlutterFragment的形式嵌入:
- 在原生Activity的布局中添加用于承载Fragment的容器,底部保留BottomNavigationBar。
- 在Activity中初始化FlutterEngine,创建
FlutterFragment并添加到容器:val flutterEngine = FlutterEngineCache.getInstance().get("for_start_engine") ?: run { val engine = FlutterEngine(this) engine.dartExecutor.executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault()) FlutterEngineCache.getInstance().put("for_start_engine", engine) engine } val flutterFragment = FlutterFragment.withCachedEngine("for_start_engine").build() supportFragmentManager.beginTransaction() .replace(R.id.flutter_container, flutterFragment) .commit()
这种方式更灵活,原生Activity完全掌控BottomNavigationBar的逻辑,Flutter仅负责内容区域。
内容的提问来源于stack exchange,提问作者Escargot

