如何实现含双按钮的Navigation Drawer:点击分别加载不同菜单项
没问题,我来帮你搞定这个带切换按钮的Navigation Drawer!咱们一步步来,从布局到代码逻辑都安排得明明白白~
整体实现思路
- 给Navigation Drawer的头部自定义一个包含两个切换按钮的布局
- 准备两组不同的菜单项资源文件
- 给两个切换按钮设置点击事件,点击时切换Navigation Drawer加载的菜单
- 给菜单项统一设置点击监听器,处理不同菜单的跳转/操作逻辑
先做一个包含两个切换按钮的头部,放在Navigation Drawer最顶部:
<?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:orientation="horizontal" android:padding="16dp" android:background="#f5f5f5"> <Button android:id="@+id/btn_menu1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="菜单组1" android:textColor="#000" android:background="@android:color/transparent" android:textSize="14sp"/> <Button android:id="@+id/btn_menu2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="菜单组2" android:textColor="#000" android:background="@android:color/transparent" android:textSize="14sp"/> </LinearLayout>
你可以给按钮加个selector背景,让选中状态更显眼,比如点击时变蓝底白字。
2. 准备两组菜单项资源
在res/menu目录下创建两个菜单文件,分别对应不同的菜单项:
第一组菜单(menu_drawer_group1.xml)
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/nav_home" android:title="首页" android:icon="@drawable/ic_home"/> <item android:id="@+id/nav_favorite" android:title="我的收藏" android:icon="@drawable/ic_favorite"/> <item android:id="@+id/nav_settings" android:title="设置" android:icon="@drawable/ic_settings"/> </group> </menu>
第二组菜单(menu_drawer_group2.xml)
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/nav_message" android:title="消息中心" android:icon="@drawable/ic_message"/> <item android:id="@+id/nav_feedback" android:title="帮助反馈" android:icon="@drawable/ic_feedback"/> <item android:id="@+id/nav_about" android:title="关于我们" android:icon="@drawable/ic_about"/> </group> </menu>
注意:两组菜单的item id不要重复,否则点击监听会混淆。
3. 主布局文件(
activity_main.xml) 用DrawerLayout包裹主内容和NavigationView,指定自定义的头部布局:
<?xml version="1.0" encoding="utf-8"?> <androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <!-- 主内容区域,这里用FrameLayout作为容器,你可以替换成自己的布局 --> <FrameLayout android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent"/> <!-- Navigation Drawer --> <com.google.android.material.navigation.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/header_drawer" app:menu="@menu/menu_drawer_group1"/> <!-- 默认加载第一组菜单 --> </androidx.drawerlayout.widget.DrawerLayout>
4. Activity代码逻辑实现(以Kotlin为例)
核心是给两个按钮设置点击事件,切换菜单并重新绑定点击监听器:
class MainActivity : AppCompatActivity() { private lateinit var drawerLayout: DrawerLayout private lateinit var navView: NavigationView private lateinit var btnMenu1: Button private lateinit var btnMenu2: Button override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化控件 drawerLayout = findViewById(R.id.drawer_layout) navView = findViewById(R.id.nav_view) // 获取头部的两个切换按钮 val headerView = navView.getHeaderView(0) btnMenu1 = headerView.findViewById(R.id.btn_menu1) btnMenu2 = headerView.findViewById(R.id.btn_menu2) // 默认选中第一个按钮,加载第一组菜单 setButtonSelected(btnMenu1, true) setButtonSelected(btnMenu2, false) setupNavItemClickListener() // 按钮点击事件:切换菜单 btnMenu1.setOnClickListener { navView.inflateMenu(R.menu.menu_drawer_group1) setButtonSelected(btnMenu1, true) setButtonSelected(btnMenu2, false) setupNavItemClickListener() // 菜单替换后重新绑定监听 } btnMenu2.setOnClickListener { navView.inflateMenu(R.menu.menu_drawer_group2) setButtonSelected(btnMenu1, false) setButtonSelected(btnMenu2, true) setupNavItemClickListener() } } // 辅助方法:设置按钮选中状态的样式 private fun setButtonSelected(button: Button, isSelected: Boolean) { button.isSelected = isSelected button.setTextColor(if (isSelected) Color.WHITE else Color.BLACK) button.setBackgroundColor(if (isSelected) Color.parseColor("#2196F3") else Color.TRANSPARENT) } // 设置菜单项的点击监听 private fun setupNavItemClickListener() { navView.setNavigationItemSelectedListener { menuItem -> when (menuItem.itemId) { // 处理第一组菜单的点击 R.id.nav_home -> Toast.makeText(this, "切换到首页", Toast.LENGTH_SHORT).show() R.id.nav_favorite -> Toast.makeText(this, "打开我的收藏", Toast.LENGTH_SHORT).show() R.id.nav_settings -> Toast.makeText(this, "进入设置页面", Toast.LENGTH_SHORT).show() // 处理第二组菜单的点击 R.id.nav_message -> Toast.makeText(this, "查看消息中心", Toast.LENGTH_SHORT).show() R.id.nav_feedback -> Toast.makeText(this, "提交帮助反馈", Toast.LENGTH_SHORT).show() R.id.nav_about -> Toast.makeText(this, "查看关于我们", Toast.LENGTH_SHORT).show() } // 点击后关闭Drawer drawerLayout.closeDrawer(GravityCompat.START) true } } }
关键注意点
- 每次切换菜单时要重新调用
setupNavItemClickListener(),因为inflateMenu()会替换掉原有的菜单,之前的监听会失效 - 如果需要更美观的按钮选中效果,可以用
StateListDrawable(selector)来定义背景,比代码里直接设置颜色更灵活 - 若要保留菜单的展开状态,可以在切换前保存当前菜单的展开状态,切换后恢复(不过一般切换菜单后默认收起,对用户体验影响不大)
内容的提问来源于stack exchange,提问作者Faxeel Ahmed
相关产品推荐
相关产品推荐

