安卓DrawerLayout - 未找到与重力匹配的抽屉视图

47
当我单击我的抽屉开关时,我会收到以下异常:
``` java.lang.IllegalArgumentException: No drawer view found with gravity LEFT ```
这是我的 `activity_drawer.xml`:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"/>

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <fragment
        android:id="@+id/navigation"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:name="com.xyz.ui.navigation.NavigationFragment"
        tools:layout="@layout/fragment_navigation" />

    </LinearLayout>
</android.support.v4.widget.DrawerLayout>

我的fragment_navigation.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<ListView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="start">

</ListView>

还有我的清单项:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Large Text"
        android:id="@+id/navigation_item_text"
        android:layout_gravity="center_horizontal" />
</LinearLayout>

在某些设备上,START==LEFT,而在另一些设备上则为==RIGHT,这是为了支持从右到左的RTL书写。请在所有设备上使用STARTLEFT来固定选择的侧面。 - snachmsm
@MikeM。不,我的Java代码中没有使用那个;) - Tobias
@Tobias:你在activity_drawer.xml中使用Fragment有什么特殊的原因吗?然后只是在其中使用一个只有ListView的布局。如果你将activity_drawer.xml中的<fragment ... />块移除并替换为ListView,会发生什么? - Squonk
你的抽屉需要放在LinearLayout之外。 - Mike M.
如果你仔细检查,你会发现确实有两个顶级元素:LinearLayout和fragment。 - asiby
10个回答

33

从文档中得知

  

要使用 DrawerLayout,将您的主要内容视图定位为宽度和高度均为 match_parent 的第一个子项。 将抽屉作为主内容视图之后的子视图添加,并适当设置 layout_gravity。 抽屉通常使用固定宽度的 match_parent 高度。

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"/>

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    </LinearLayout>

    <fragment
        android:id="@+id/navigation"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="right"
        android:name="com.xyz.ui.navigation.NavigationFragment"
        tools:layout="@layout/fragment_navigation" />

</android.support.v4.widget.DrawerLayout>

简单的解决方案为我解决了这个错误。谢谢! - John T

20


好的。让我在这里简化和澄清一下。
什么是DrawerLayouthttps://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html

DrawerLayout 作为窗口内容的顶层容器,可以从窗口边缘拉出交互式“抽屉”视图。抽屉的定位和布局使用子视图上的android:layout_gravity属性进行控制,该属性对应于您希望抽屉从哪侧的视图中出现:左侧或右侧。(在支持布局方向的平台版本上,则为start / end。)要使用DrawerLayout,请将主要内容视图定位为第一个具有匹配父项的宽度和高度的子项。在主内容视图之后添加抽屉作为子视图,并适当设置layout_gravity。抽屉通常使用固定宽度的match_parent高度。


用简单的话来说,什么是DrawerLayout
  • Android支持的布局,允许您在主屏幕上叠加一个称为抽屉的覆盖屏幕。
  • 与LinearLayout和RelativeLayout类似,DrawerLayout需要子视图才能工作。
  • 子视图必须设置以下属性之一
    android:layout_gravity="start"android:layout_gravity="left"
  • DrawerLayout使用此childView了解从哪里开始显示抽屉,即从左到右还是从右到左。有些国家的文本是从右到左阅读的。


技术细节:
  • EVENT#1:将ActionBarDrawerToggle.java设置为DrawerLayout的抽屉侦听器
  •     DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
        ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
                    toolbar,R.string.navigation_drawer_open,
                    R.string.navigation_drawer_close)
                    mDrawerLayout.setDrawerListener(mDrawerToggle);
        
  • EVENT#2:用户单击Toolbar.navigationIcon,调用toggle()函数
    ActionBarDrawerToggle.java(android-sdk\sources\android-22\android\support\v7\app\ActionBarDrawerToggle.java)
        private void toggle() { 
            if (mDrawerLayout.isDrawerVisible(GravityCompat.START)) {
                mDrawerLayout.closeDrawer(GravityCompat.START); 
            } else {
                mDrawerLayout.openDrawer(GravityCompat.START); 
            } 
        } 
        

    Gravity.java(android-sdk\sources\android-22\android\view\Gravity.java)
    /** Push object to x-axis position at the start of its container,
        not changing its size.*/ 
        public static final int START = RELATIVE_LAYOUT_DIRECTION | Gravity.LEFT; 
        
  • EVENT#3:Toggle()函数调用mDrawerLayout.openDrawer(Gravity.START)
    DrawerLayout.java(support-v4-22.1.1.jar库)
        /*** Open the specified drawer by animating it out of view. **
        @param gravity Gravity.LEFT to move the left drawer or Gravity.RIGHT
        for the right. * GravityCompat.START or GravityCompat.END may also
        be used. */ 
        public void openDrawer(@EdgeGravity int gravity) { 
            final View drawerView = findDrawerWithGravity(gravity); 
            if
        <android.support.v4.widget.DrawerLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/drawer_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true">
        <!--This will appear when the drawer is closed (default view)--> 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"> 
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:minHeight="?attr/actionBarSize"
                android:background="?attr/colorPrimary" /> 
        </LinearLayout> 
        <!-- This will appear when the drawer is opened -->
        <!-- the property,android:layout_gravity, is used internally to identify imageView as the view to be displayed when the drawer is opened -->
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height=" match_parent"
            android:layout_gravity="left"
            android:background="@drawable/img_shree_ganesha" /> 
    
        </android.support.v4.widget.DrawerLayout>
    I hope that helps. Happy Coding…
    

10
"Android抽屉"需要是"DrawerLayout"的直接子节点。
在您上面的示例中(有关原始问题的示例),您只在"DrawerLayout"下拥有一个直接子节点("LinearLayout"),并且之后没有抽屉视图。
将您的抽屉视图移出LinearLayout并将其放置在其后。

4

在我的情况下,因为DrawerLayout属性: tools:openDrawer="start" 我为第二个元素添加了android:layout_gravity="start"

 <android.support.v4.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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:openDrawer="right"
    tools:context=".map.MapFragment">

<include layout="@layout/fragment_map" />

<FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="right"
        android:background="@color/white"
        android:fitsSystemWindows="true"
        app:menu="@menu/drawer_view"
        app:headerLayout="@layout/drawer_nav_header"/>

</android.support.v4.widget.DrawerLayout>

正是我所缺少的。如果没有与NavigationView的layout_gravity匹配的tools:openDrawer工具,我将像原帖中一样遭遇崩溃。 - Jaymes Bearden

4

android:layout_gravity="start"

添加到 NavigationView 中

像这样:

<com.google.android.material.navigation.NavigationView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:headerLayout="@layout/drawer_menu"
    android:layout_gravity="start"
    android:foregroundGravity="right"
    android:id="@+id/nv">

    <include layout="@layout/drawer_menu"/>
</com.google.android.material.navigation.NavigationView>

2
你是否使用从右到左(RTL)的布局?在RTL布局上设置重力左侧会引发此异常。可以通过设置重力开始而不是左侧来解决此问题。

2

I solve this problem like this :

XML :

<?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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:layoutDirection="rtl"
    tools:openDrawer="end"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <include
            layout="@layout/toolbar_main"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <include layout="@layout/content_main" />

    </LinearLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigationView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:layoutDirection="rtl"
        android:background="@color/white"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/menu_drawer" />

</androidx.drawerlayout.widget.DrawerLayout>

Java中的AND操作:

 if (mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.END)) {
        mDrawerLayout.closeDrawer(GravityCompat.END);
    }

我希望这能对某些人有所帮助!


1
你应该在DrawerLayout和NavigationView中使用相同的重力:例如,在DrawerLayout标记中使用tools:openDrawer="right",在NavigationView标记中使用android:layout_gravity="right"。
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:openDrawer="right"
    tools:context=".map.MapFragment">

<include layout="@layout/fragment_map" />
<FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="right"
        android:background="@color/white"
        android:fitsSystemWindows="true"
        app:menu="@menu/drawer_view"
        app:headerLayout="@layout/drawer_nav_header"/>

</android.support.v4.widget.DrawerLayout>

0

java.lang.IllegalArgumentException: No drawer view found with gravity LEFT

解决方法 如果您的抽屉布局已经有一个子视图,请为其中一个子视图分配 layout_gravity = "start" 或 "left" 属性。或者, 在您的 DrawerLayout 视图中创建一个子视图,并赋予它一个 layout_gravity = "start" 或 "left" 属性。 例如:

 <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.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"
        android:id="@+id/mDrawer_Layout"
        tools:context="com.rad5.matdesign.MainActivity">

        <android.support.design.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v4.widget.DrawerLayout
                android:id="@+id/drawer_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                tools:openDrawer="start">

    <!-- Notice that here an image view as a child of the Drawer layout was -->
    <!-- given a layout_gravity="start" -->

                <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="start"/>

            </android.support.v4.widget.DrawerLayout>

            <android.support.design.widget.AppBarLayout
                android:id="@+id/appBar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:background="?attr/colorPrimary"/>

                <android.support.design.widget.TabLayout
                    android:id="@+id/tabs"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
            </android.support.design.widget.AppBarLayout>

            <android.support.v4.view.ViewPager
                android:id="@+id/viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_behavior="@string/appbar_scrolling_view_behavior" />

        </android.support.design.widget.CoordinatorLayout>

        <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header"
            app:menu="@menu/menu_navigation_items" />

    </android.support.design.widget.CoordinatorLayout>

0

替换后错误已修复

<fragment
        android:id="@+id/fragmentContainerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.example.MyFragment"/>

使用

<androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragmentContainerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start" />

在onCreate()中添加了Fragment实例到FragmentContainerView。
supportFragmentManager.beginTransaction()
    .add(R.id.fragmentContainerView, MyFragment())
    .commit()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接