Android Studio实现Navigation Drawer替换为DrawerLayout后UI错乱问题咨询
问题根源
你当前布局错乱的核心原因是DrawerLayout的使用规则不符合要求:
- DrawerLayout作为根布局时,仅允许最多2个直接子控件:第一个是页面主内容容器,第二个是侧边抽屉控件(也就是你的NavigationView)
- 你现在把原本属于主内容的Toolbar、TextView、MaterialCardView等所有控件都直接作为DrawerLayout的子元素,这些控件设置的
app:layout_constraintXXX属性在DrawerLayout下完全不生效,自然会出现布局错乱。 - 你之前用ConstraintLayout做根布局时崩溃,是因为ActionBarDrawerToggle必须绑定DrawerLayout实例,找不到对应DrawerLayout就会抛出异常。
方案1:修正DrawerLayout布局结构(更推荐,官方实现兼容性好)
你只需要把原来所有主内容的控件,整体包裹到一个ConstraintLayout里,作为DrawerLayout的第一个直接子元素即可,修改后的布局结构如下:
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/background" android:id="@+id/drawerlayout" tools:context=".MainActivity"> <!-- 第一层:主内容容器,用ConstraintLayout包裹所有原有主内容控件 --> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/background" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:title="Toolbars" app:titleTextColor="#FFFFFF" app:titleMarginStart = "10dp" android:layout_marginBottom="5dp" app:layout_constraintTop_toTopOf="parent"/> <View android:id="@+id/viewHeaderBackground" android:layout_width="match_parent" android:layout_height="@dimen/_125sdp" android:background="@color/primary" app:layout_constraintTop_toTopOf="parent"/> <com.github.ybq.android.spinkit.SpinKitView android:id="@+id/spin_kit" style="@style/SpinKitView.Large.Circle" android:layout_width="wrap_content" android:layout_height="wrap_content" app:SpinKit_Color="@color/validation" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> <TextView android:id="@+id/textTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/_16sdp" android:layout_marginLeft="@dimen/_16sdp" android:layout_marginTop="@dimen/_16sdp" android:text="Cash Grants" android:textColor="@color/white" android:textSize="@dimen/_20ssp" android:textStyle="bold" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent"/> <androidx.appcompat.widget.AppCompatImageView android:layout_width="@dimen/_26sdp" android:layout_height="@dimen/_26sdp" android:layout_marginEnd="@dimen/_16sdp" android:layout_marginRight="@dimen/_16sdp" android:src="@drawable/dswd_logo" app:layout_constraintBottom_toBottomOf="@id/textTitle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@id/textTitle" app:tint="@color/white"/> <com.google.android.material.card.MaterialCardView android:id="@+id/cardHeader" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="@dimen/_16sdp" android:layout_marginEnd="@dimen/_16sdp" app:cardBackgroundColor="@color/card_background" app:cardCornerRadius="@dimen/_16sdp" app:layout_constraintBottom_toBottomOf="@id/viewHeaderBackground" app:layout_constraintTop_toBottomOf="@id/viewHeaderBackground"> <!-- 这里保留你原来CardView里的内容不变 --> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="@dimen/_14sdp"> <!-- 原有内部代码完全不用改 --> </androidx.constraintlayout.widget.ConstraintLayout> </com.google.android.material.card.MaterialCardView> <ScrollView android:layout_width="match_parent" android:layout_height="0dp" android:clipToPadding="false" android:overScrollMode="never" android:padding="@dimen/_16sdp" android:scrollbars="none" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/cardHeader"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <include layout="@layout/dashboard_item_1"/> <include layout="@layout/dashboard_item_2"/> <include layout="@layout/dashboard_item_3"/> <include layout="@layout/dashboard_item_4"/> </LinearLayout> </ScrollView> </androidx.constraintlayout.widget.ConstraintLayout> <!-- 第二层:侧边抽屉控件,放在最后即可 --> <com.google.android.material.navigation.NavigationView android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/navigationview" app:headerLayout="@layout/sidebar_header" app:menu="@menu/sidemenu" android:layout_gravity="start"/> </androidx.drawerlayout.widget.DrawerLayout>
修改后你的Java代码完全不需要改动,就能同时保留原有UI正常显示和侧边导航功能。
方案2:用ConstraintLayout实现侧边导航(适合需要高度自定义的场景)
如果不想用DrawerLayout也可以自行实现:
- 在根ConstraintLayout里加入侧边栏布局,设置
app:layout_constraintStart_toStartOf="parent"、app:layout_constraintTop_toTopOf="parent",默认设置android:translationX="-100%"隐藏在屏幕左侧 - 去掉原来的ActionBarDrawerToggle代码,自己给Toolbar的导航按钮设置点击事件,用属性动画控制侧边栏的translationX实现滑入滑出,同时可以自己加半透明遮罩、边缘滑动手势等效果
- 这种方案需要自行处理所有交互逻辑,没有特殊需求优先选方案1。
内容的提问来源于stack exchange,提问作者CarlJade
相关产品推荐
相关产品推荐

