Android中BottomNavigation中间放置FAB/ImageButton的实现方法咨询
没问题!要实现这种中间带操作按钮的BottomNavigation,我给你两种实用方案,一步步来就能搞定:

这个方案用Google官方的Material组件组合,简单省心,适合大多数场景:
- 编写布局文件
用CoordinatorLayout作为根布局,把BottomNavigationView和FAB放在底部,通过锚点和偏移量让FAB嵌在导航栏中间:
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout 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"> <!-- 主内容容器,用来放Fragment或其他页面内容 --> <FrameLayout android:id="@+id/main_content_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/bottom_navigation"/> <!-- 底部导航栏 --> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_navigation" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="@color/white" app:menu="@menu/bottom_nav_menu"/> <!-- 中间的FAB按钮 --> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/middle_fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_add" app:layout_anchor="@id/bottom_navigation" app:layout_anchorGravity="center_horizontal|top" android:layout_marginTop="-32dp"/> <!-- 偏移量设为FAB高度的一半,刚好嵌在导航栏中间 --> </androidx.coordinatorlayout.widget.CoordinatorLayout>
- 配置导航菜单
在res/menu/bottom_nav_menu.xml里添加菜单选项,注意给中间的FAB留空位置(比如设置一个不可点击的空item):
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/nav_home" android:icon="@drawable/ic_home" android:title="首页"/> <item android:id="@+id/nav_search" android:icon="@drawable/ic_search" android:title="搜索"/> <!-- 空item占位置,避免导航栏选项挤在一起 --> <item android:id="@+id/nav_placeholder" android:icon="@android:color/transparent" android:title="" android:enabled="false"/> <item android:id="@+id/nav_profile" android:icon="@drawable/ic_profile" android:title="我的"/> </menu>
- 处理点击逻辑
在Activity或Fragment里给导航栏和FAB设置点击事件,同时跳过中间的空item:
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_navigation) val middleFab = findViewById<FloatingActionButton>(R.id.middle_fab) // 底部导航栏选中事件 bottomNav.setOnItemSelectedListener { menuItem -> when (menuItem.itemId) { R.id.nav_home -> { // 切换到首页Fragment或执行首页逻辑 true } R.id.nav_search -> { // 切换到搜索Fragment或执行搜索逻辑 true } R.id.nav_profile -> { // 切换到个人中心Fragment或执行个人中心逻辑 true } else -> false // 忽略中间的空item } } // 中间FAB点击事件 middleFab.setOnClickListener { // 执行你需要的操作,比如打开添加页面、触发提交等 }
方案二:自定义布局实现高度定制
如果需要更灵活的样式(比如自定义按钮形状、带文字的按钮),可以直接写一个自定义的底部导航布局:
- 编写自定义底部布局
用LinearLayout平分宽度,中间的按钮单独用容器包裹并向上偏移:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="@color/white" android:orientation="horizontal" android:paddingVertical="8dp" android:elevation="8dp"> <!-- 首页按钮 --> <ImageView android:id="@+id/btn_home" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:src="@drawable/ic_home" android:scaleType="centerInside" android:padding="8dp"/> <!-- 搜索按钮 --> <ImageView android:id="@+id/btn_search" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:src="@drawable/ic_search" android:scaleType="centerInside" android:padding="8dp"/> <!-- 中间自定义按钮容器 --> <LinearLayout android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:gravity="center"> <ImageButton android:id="@+id/btn_middle_action" android:layout_width="64dp" android:layout_height="64dp" android:src="@drawable/ic_add" android:background="@drawable/custom_button_bg" android:layout_marginTop="-32dp" android:scaleType="centerInside"/> </LinearLayout> <!-- 通知按钮 --> <ImageView android:id="@+id/btn_notify" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:src="@drawable/ic_notify" android:scaleType="centerInside" android:padding="8dp"/> <!-- 个人中心按钮 --> <ImageView android:id="@+id/btn_profile" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:src="@drawable/ic_profile" android:scaleType="centerInside" android:padding="8dp"/> </LinearLayout>
- 自定义按钮背景
在res/drawable/custom_button_bg.xml里写一个圆形背景:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="@color/teal_200"/> <!-- 设置你想要的按钮颜色 --> <size android:width="64dp" android:height="64dp"/> </shape>
- 处理点击与选中状态
在代码里给每个按钮设置点击事件,同时处理选中时的图标颜色切换:
val btnHome = findViewById<ImageView>(R.id.btn_home) val btnSearch = findViewById<ImageView>(R.id.btn_search) val btnMiddle = findViewById<ImageButton>(R.id.btn_middle_action) val btnNotify = findViewById<ImageView>(R.id.btn_notify) val btnProfile = findViewById<ImageView>(R.id.btn_profile) // 首页按钮点击 btnHome.setOnClickListener { resetNavIconColors() btnHome.setColorFilter(ContextCompat.getColor(this, R.color.teal_200)) // 切换首页内容 } // 搜索按钮点击 btnSearch.setOnClickListener { resetNavIconColors() btnSearch.setColorFilter(ContextCompat.getColor(this, R.color.teal_200)) // 切换搜索内容 } // 中间按钮点击 btnMiddle.setOnClickListener { // 执行自定义操作 } // 通知按钮点击 btnNotify.setOnClickListener { resetNavIconColors() btnNotify.setColorFilter(ContextCompat.getColor(this, R.color.teal_200)) // 切换通知内容 } // 个人中心按钮点击 btnProfile.setOnClickListener { resetNavIconColors() btnProfile.setColorFilter(ContextCompat.getColor(this, R.color.teal_200)) // 切换个人中心内容 } // 重置所有导航图标为默认颜色 private fun resetNavIconColors() { val defaultColor = ContextCompat.getColor(this, R.color.grey_600) btnHome.setColorFilter(defaultColor) btnSearch.setColorFilter(defaultColor) btnNotify.setColorFilter(defaultColor) btnProfile.setColorFilter(defaultColor) }
这两种方案都能完美实现你要的效果,第一种适合快速开发,第二种适合需要高度定制按钮样式的场景~
内容的提问来源于stack exchange,提问作者Sanath
相关产品推荐
相关产品推荐

