工具栏下方的导航抽屉

68

我正在尝试让导航抽屉在工具栏下方打开。

<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/drawer_layout"
tools:context=".MainActivity">
<RelativeLayout
    android:layout_width = "match_parent"
    android:layout_height = "wrap_content">
    <include layout="@layout/toolbar"
        android:id="@+id/toolbar"/>
    <FrameLayout
        android:layout_below="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/background_color"/>
</RelativeLayout>
<ListView
    android:id="@+id/drawer"
    android:layout_width="260dp"
    android:layout_height="match_parent"
    android:layout_below="@+id/toolbar"
    android:layout_marginTop="56dp"
    android:layout_gravity="start">
</ListView>
</android.support.v4.widget.DrawerLayout>

我该如何重新格式化 XML,使得导航栏在工具栏下方打开?


1
@tyczj 如果你看最新版本的Google Play商店,你会发现导航抽屉在工具栏下面。我想实现类似的功能。 - safaiyeh
@tyczj 当导航栏打开时,我该如何处理工具栏操作? - safaiyeh
如果你希望在抽屉打开时用户执行某些操作,那么这些操作应该放在抽屉的布局中。 - tyczj
可能是重复的问题,与如何使DrawerLayout显示在工具栏下方?相同。 - Shirish Herwade
7个回答

124

您应该将DrawerLayout作为顶级父级容器,并将Toolbar移出DrawerLayout的内容容器。

简而言之,应该是这样的:

RelativeLayout
 ----Toolbar
 ----DrawerLayout
     ---ContentView
     ---DrawerList 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/top_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar" />

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/toolbar">

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

        <ListView
            android:id="@+id/drawer"
            android:layout_width="260dp"
            android:layout_height="match_parent"
            android:layout_below="@+id/toolbar"
            android:layout_gravity="start"
            android:layout_marginTop="56dp" />

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

然而,Material Design指南规定导航抽屉应该在Toolbar上方。


这将使我能够处理工具栏操作,即使抽屉已打开? - safaiyeh
1
是的。因为抽屉只会响应其边界矩形的事件。 - Nikola Despotoski
但是状态栏现在重叠在工具栏上了。如何解决这个问题? - Diffy
1
fitsystemwindows设置为true会导致那个问题。无论如何已经解决了。 - Diffy
5
尼古拉,你的回答很好!只需稍作改进。对于ListView,请使用android:layout_marginTop="?attr/actionBarSize",在工具栏中设置的值与高度相同。 - Juan Saravia
显示剩余2条评论

24
你应该简单地添加。
android:layout_marginTop="@dimen/abc_action_bar_default_height_material"

把它添加到您用作抽屉的布局中。

这将自动调整工具栏下方的导航抽屉,并支持不同的屏幕大小。


9
很遗憾,在兼容性库中,@dimen/abc_action_bar_default_height_material被标记为私有的,因此这种解决方案不安全使用,因为资源名称可能会在将来的库版本中消失。 - Ted Hopp
5
在滑出时,它仍会在工具栏上产生阴影。这不是期望的效果,也不是最好的处理方式。 - Ali Kazi

19

您可以像这样添加layout_marginTop

<android.support.design.widget.NavigationView
        android:layout_marginTop="@dimen/abc_action_bar_default_height_material"
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

但是抽屉将出现作为顶层到工具栏。


这里有另一种添加它到工具栏下面的不太流畅的方法!!!

可能不是最好的方法,但它可以工作!

最终结果会看起来像这样

enter image description here

如果你创建一个导航抽屉项目(Navigation Drawer Activity),它会在创建时在你的layout文件夹中给你四个XML文件

  • app_bar_main
  • content_main
  • navigatin_main
  • activity_main

    enter image description here

这些xml如何链接?大多数情况下,会使用include标签

您的Activity与activity_main相关联

  • activity_main包含app_bar_mainnavigation_view(抽屉)
  • app_bar_main默认包含toolbarcontent_main

现在让我们删除activity_main并将其内容直接设置为app bar main,并将其用作Activity的主布局。

要将抽屉添加到工具栏下方,请将其添加到android.support.design.widget.AppBarLayout下,因为它包含工具栏并且应该在顶部。

这里是app_bar_main.XML的示例

      <?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:fitsSystemWindows="true"
    tools:context="none.navhead.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.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" />

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



    //------ taken from activity_main
    // content main
    <include layout="@layout/content_main" />

    // you need this padding
    <android.support.v4.widget.DrawerLayout
        android:paddingTop="?attr/actionBarSize"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:openDrawer="start">

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

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


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

p.s. 你可以将 app_bar_main.XML 设置为你的活动的 setContentView,尽管有很多方法可以玩耍 ;)


7
这个方法在API23上也适用于我,其中NavigationView被设计成绘制在系统状态栏后面。但是,它仍然在顶部绘制阴影,就好像它仍然绘制在状态栏后面一样,所以我不得不将app:insetForeground="@null"添加到NavigationView中,这样它就可以正确地在操作栏(或实际上是工具栏)下方绘制了。这样也可以使左上角漂亮的动画箭头可见,并且不会被NavigationView遮挡。 - Pointer Null
还有,我需要将android:layout_marginTop="?attr/actionBarSize"添加到DrawerLayout中,以确保内容和导航正确可见。 - Sucipto
1
当我使用它时,片段中的数据无法点击。请告诉我如何解决。 - roshan posakya
@roshan posakya,你把你的片段放在哪里了? - Charuක
@Charuka 感谢您的回复,但我使用了不同的方法解决了这个问题。 - roshan posakya
@PointerNull,你的 app:insetForeground="@null" 真是救了我的一天。它可以隐藏抽屉上方的阴影。 - Tejas Pandya

9
这是我的布局,功能完美: activity_main:
<?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">
    <!-- AppBarLayout should be here -->
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.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" />
    </android.support.design.widget.AppBarLayout>

    <!-- add app:layout_behavior="@string/appbar_scrolling_view_behavior" -->

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

        <include
            layout="@layout/app_bar_main"
            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="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header_main"
            app:menu="@menu/activity_main_drawer" />
    </android.support.v4.widget.DrawerLayout>
</android.support.design.widget.CoordinatorLayout>

app_bar_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:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true"
  tools:context=".activty.MainActivity">
<include layout="@layout/content_main"/>
</FrameLayout>

结果:下方工具栏

在此输入图片描述


这个适用于将它放在具有可折叠图像的可折叠工具栏下面。它保持在图像下方。 - rosegrink
完美。它应该适用于每个人。 - Sakhawat Hossain

3
<?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"
    android:fitsSystemWindows="false"
    tools:openDrawer="start">
    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <android.support.design.widget.NavigationView
        android:layout_marginTop="?attr/actionBarSize"
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="false"
        app:menu="@menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>

android:fitsSystemWindows="false": - Tarun Umath

3
如果您正在使用自定义工具栏,则可以这样使用抽屉布局...
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

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

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

        <!-- drawer view -->
        <LinearLayout
            android:layout_width="304dp"
            android:layout_height="match_parent"
            android:layout_gravity="left|start">
            ....
        </LinearLayout>

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

</LinearLayout>

如果您没有使用自定义工具栏,则需要将顶部边距设置为抽屉布局。
android:layout_marginTop ="?android:attr/actionBarSize"

0
一个简单而好的解决方案是将fitsSystemWindows=false设置为。
android.support.v4.widget.DrawerLayout

具有ID为

android:id="@+id/drawer_layout"

对于navigationView,将layout_marginTop设置为?attr/actionBarSize,这将获取操作栏的大小并将其设置为边距。

这里是完整代码 activity_main.xml,其中包含上述更改。


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