如何在单个Activity中实现多个DrawerLayout?
同一Activity中实现多个DrawerLayout的方案
需求说明
需求:在同一个Activity中打开多个导航页面(DrawerLayout),一个通过Toolbar触发,其他通过普通按钮触发。已知
OpenDrawer(GravityCompat.Start);可实现按钮打开侧边栏,寻求多DrawerLayout的实现方法。
环境:基于默认导航项目修改
已执行操作:将activity_main.xml的根布局改为FrameLayout,添加2个DrawerLayout;在app_bar_main.xml中新增一个Toolbar。
现有代码问题修正
- app_bar_main.xml布局错误:AppBarLayout内部存在无效的冗余标签,导致Toolbar无法正常渲染
- MainActivity控件绑定错误:获取第二个Toolbar时误绑定了第一个Toolbar的ID,导致第二个DrawerLayout的Toggle无法正常工作
- DrawerLayout重叠问题:两个DrawerLayout直接放在FrameLayout中会重叠,需要通过显示状态控制避免冲突
完整修正代码
1. activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout 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:id="@+id/frame_drawer" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 第一个DrawerLayout:通过Toolbar触发 --> <androidx.drawerlayout.widget.DrawerLayout android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" /> <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" android:fitsSystemWindows="true" app:menu="@menu/activity_main_drawer" /> </androidx.drawerlayout.widget.DrawerLayout> <!-- 第二个DrawerLayout:默认隐藏,通过按钮触发 --> <androidx.drawerlayout.widget.DrawerLayout android:id="@+id/drawer_layout2" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:visibility="gone" tools:openDrawer="start"> <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.google.android.material.navigation.NavigationView android:id="@+id/nav_view2" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:menu="@menu/activity_main_drawer" /> </androidx.drawerlayout.widget.DrawerLayout> </FrameLayout>
2. app_bar_main.xml
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar2" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </com.google.android.material.appbar.AppBarLayout> <include layout="@layout/content_main" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" app:srcCompat="@android:drawable/ic_dialog_email" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
3. MainActivity.cs
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)] public class MainActivity : AppCompatActivity, NavigationView.IOnNavigationItemSelectedListener { private DrawerLayout _drawerLayout1; private DrawerLayout _drawerLayout2; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); SetContentView(Resource.Layout.activity_main); // 初始化第一个Toolbar和DrawerLayout Toolbar toolbar1 = FindViewById<Toolbar>(Resource.Id.toolbar); SetSupportActionBar(toolbar1); SupportActionBar.Title = "Site 1"; _drawerLayout1 = FindViewById<DrawerLayout>(Resource.Id.drawer_layout); ActionBarDrawerToggle toggle1 = new ActionBarDrawerToggle(this, _drawerLayout1, toolbar1, Resource.String.navigation_drawer_open, Resource.String.navigation_drawer_close); _drawerLayout1.AddDrawerListener(toggle1); toggle1.SyncState(); NavigationView navView1 = FindViewById<NavigationView>(Resource.Id.nav_view); navView1.SetNavigationItemSelectedListener(this); // 初始化第二个Toolbar和DrawerLayout Toolbar toolbar2 = FindViewById<Toolbar>(Resource.Id.toolbar2); toolbar2.Title = "Site 2"; toolbar2.SetNavigationIcon(Resource.Drawable.ic_menu); toolbar2.NavigationClick += (s, e) => { _drawerLayout1.Visibility = ViewStates.Gone; _drawerLayout2.Visibility = ViewStates.Visible; _drawerLayout2.OpenDrawer(GravityCompat.Start); }; _drawerLayout2 = FindViewById<DrawerLayout>(Resource.Id.drawer_layout2); _drawerLayout2.AddDrawerListener(new DrawerLayout.SimpleDrawerListener() { public override void OnDrawerClosed(View drawerView) { base.OnDrawerClosed(drawerView); _drawerLayout2.Visibility = ViewStates.Gone; _drawerLayout1.Visibility = ViewStates.Visible; } }); NavigationView navView2 = FindViewById<NavigationView>(Resource.Id.nav_view2); navView2.SetNavigationItemSelectedListener(this); // 绑定FAB点击事件打开第二个DrawerLayout FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab); fab.Click += FabOnClick; } private void FabOnClick(object sender, EventArgs eventArgs) { _drawerLayout1.Visibility = ViewStates.Gone; _drawerLayout2.Visibility = ViewStates.Visible; _drawerLayout2.OpenDrawer(GravityCompat.Start); } public bool OnNavigationItemSelected(IMenuItem item) { int id = item.ItemId; // 按需添加菜单点击逻辑 if (_drawerLayout1.IsDrawerOpen(GravityCompat.Start)) { _drawerLayout1.CloseDrawer(GravityCompat.Start); } if (_drawerLayout2.IsDrawerOpen(GravityCompat.Start)) { _drawerLayout2.CloseDrawer(GravityCompat.Start); } return true; } public override void OnBackPressed() { if (_drawerLayout1.IsDrawerOpen(GravityCompat.Start)) { _drawerLayout1.CloseDrawer(GravityCompat.Start); } else if (_drawerLayout2.IsDrawerOpen(GravityCompat.Start)) { _drawerLayout2.CloseDrawer(GravityCompat.Start); } else { base.OnBackPressed(); } } }
关键实现要点
- 布局控制:两个DrawerLayout通过
android:visibility属性切换显示状态,避免界面重叠 - Toolbar处理:一个Activity仅能设置一个
SupportActionBar,第二个Toolbar通过手动添加导航图标和点击事件触发对应DrawerLayout - Drawer监听:给第二个DrawerLayout添加关闭监听,自动恢复第一个DrawerLayout的显示
- 返回键适配:优先关闭当前打开的侧边栏,再处理默认返回逻辑
内容的提问来源于stack exchange,提问作者yuki yuki
相关产品推荐
相关产品推荐

