Android Navigation Drawer on top ActionBar

66,640

Solution 1

I have a tiny "trick" learnt from https://github.com/jfeinstein10/SlidingMenu to implement the effect you required.

You only need to remove the first child of the window's decor view, and add the first child to your drawer's content view. After that, you only need to add your drawer to the window's decor view.

Below is some detailed steps for you to do that.

First, create a xml named "decor.xml" or anything you like. Only put the DrawerLayout and the drawer in. The "FrameLayout" below is just a container. We will use it to wrap your activity's content.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout ...>
    <FrameLayout android:id="@+id/container"
        android:orientation="vertical" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"/>
    <fragment android:name="com...." 
        android:layout_gravity="start" 
        android:id="@id/navigation" 
        android:layout_width="@dimen/navigation_menu_width" 
        android:layout_height="fill_parent" />
</android.support.v4.widget.DrawerLayout>

and then remove the DrawerLayout in your main layout. Now the layout of your main activity should look like

<RelativeLayout android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent">
    ...
</RelativeLayout>

we assume that the main activity's layout is named "main.xml".

in your MainActivity, write as the following:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Inflate the "decor.xml"
    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    DrawerLayout drawer = (DrawerLayout) inflater.inflate(R.layout.decor, null); // "null" is important.

    // HACK: "steal" the first child of decor view
    ViewGroup decor = (ViewGroup) getWindow().getDecorView();
    View child = decor.getChildAt(0);
    decor.removeView(child);
    FrameLayout container = (FrameLayout) drawer.findViewById(R.id.container); // This is the container we defined just now.
    container.addView(child);

    // Make the drawer replace the first child
    decor.addView(drawer);

    // Do what you want to do.......

}

Now you've got a DrawerLayout which can slide over the ActionBar. But you might find it covered by status bar. You might need to add a paddingTop to the Drawer in order to fix that.

Solution 2

UPDATE: How to overlay the actionbar with nav drawer. (With the new Toolbar) Use these in your dependencies in your build.gradle

compile 'com.android.support:appcompat-v7:21.0.0'
compile 'com.android.support:support-v4:21.0.0'

This as your drawerlayout

<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<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">
    <LinearLayout
        android:id="@+id/layout_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    <include layout="@layout/toolbar"/>
    <!-- As the main content view, the view below consumes the entire
         space available using match_parent in both dimensions. -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"/>

    </LinearLayout>
    <fragment android:id="@+id/navigation_drawer"
        android:layout_width="@dimen/navigation_drawer_width"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/list_background"
         />

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

Make new toolbar.xml file in your layout folder.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    android:minHeight="?attr/actionBarSize"
    android:background="?attr/colorPrimary" />

Go to you activity which extend the navigation drawer. and add this after SetContentView()

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

Don't forget to extend your theme NoActionBar in your values folder.

<style name="Theme.Whtsnxt" parent="@style/Theme.AppCompat.Light.NoActionBar">
    <item name="windowActionBar">false</item>
    <!-- colorPrimary is used for the default action bar background -->
    <item name="windowActionModeOverlay">true</item>
    <item name="android:textColorPrimary">@color/white</item>
    <item name="colorPrimary">@color/splashscreen</item>
    <item name="colorPrimaryDark">@color/holo_blue_light</item>

    <item name="android:windowBackground">@color/white</item>
    <item name="android:colorBackground">@color/white</item>

</style>

Solution 3

If you do not want to use a lib or this hack:

  1. Extend "Theme.AppCompat.NoActionBar"
  2. Move the first Element of your DrawerLayout into a LinearLayout.
  3. Add a Toolbar to this LinearLayout.

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:minHeight="?attr/actionBarSize"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:titleTextColor="@android:color/white"
        android:background="?attr/colorPrimary">
    </android.support.v7.widget.Toolbar>
    
  4. in Activity add following line after setContentView

    setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
    
  5. now it should work.
Share:
66,640
lemycanh
Author by

lemycanh

Updated on July 09, 2022

Comments

  • lemycanh
    lemycanh almost 2 years

    I'm trying to make the navigation drawer over the action bar when it was slide to the right like this app: [Removed]

    This is my main activity's layout:

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v4.widget.DrawerLayout ...>
        <RelativeLayout android:orientation="vertical" 
            android:layout_width="fill_parent" 
            android:layout_height="fill_parent">
            ...
        </RelativeLayout>
        <fragment android:name="com...." 
            android:layout_gravity="start" 
            android:id="@id/navigation" 
            android:layout_width="@dimen/navigation_menu_width" 
            android:layout_height="fill_parent" />
    </android.support.v4.widget.DrawerLayout>
    

    Some other questions on stackoverflow are similar such as this question but all answers are recommend to use sliding menu lib. But this app they still use android.support.v4.widget.DrawerLayout and they succeed. Don't ask me how I know they use the standard navigation drawer but I sure about it.

    Would be really appreciate for your helps.


    HERE IS THE FINAL SOLUTION: many thanks to @Peter Cai THIS WORKS PERFECTLY. https://github.com/lemycanh/DrawerOnTopActionBar

    Screen Capture Translucent on KitKat

  • lemycanh
    lemycanh about 10 years
    You can use apktool to see the layout. It is bad but I have no way :(
  • afollestad
    afollestad over 9 years
    This library should not be used. It hasn't been updated for a very long time, and it goes against the design guidelines when Google has the DrawerLayout. Look at the Google I/O app, specifically the Material version for Android L (it's on the GitHub page: github.com/google/iosched). The DrawerLayout can cover the action bar.
  • Richard Lindhout
    Richard Lindhout over 9 years
    At the time of the answer there weren't solutions like this I know! Thanks for your suggestion I edited the answer!
  • lemycanh
    lemycanh over 9 years
    Confirmed this hack works as expected. We need to add padding to drawer, here is the trick to get status bar height: stackoverflow.com/questions/20584325/…. Another hack is when we want to add fragment to container, instead of adding like this: fragmentTransaction.replace(R.id.container, fragment); We should replace to R.id.content. fragmentTransaction.replace(getContentIdResource(), fragment); ... private int getContentIdResource() { return getResources().getIdentifier("content", "id", "android"); }
  • Admin
    Admin over 9 years
    @lemycanh Another solution that I use to add fragment is to add a container in main layout. The drawer layout has been split from the main layout, so R.id.container is only to wrap layout defined in main.xml.
  • uLYsseus
    uLYsseus over 9 years
    great answer ! After implementing this, I realized that we are actually stealing a view from another layout and ditching it ! ha ha
  • Mustafa Güven
    Mustafa Güven over 9 years
    I arranged my code as above but something went wrong with my actionbar. The toggle button which opens/close navigation drawer is appeared. Do you guess why?
  • Shubham A.
    Shubham A. almost 9 years
    After implementing this, my action bar appears to be blurred at bottom. Also, I need to add paddingTop attribute ( = 80dp ) in each fragment I replace on selection of a navigation drawer item. Why is this happening?
  • fupduck
    fupduck over 6 years
    now saw that here is the same answer but with more code.
  • dxpelou
    dxpelou over 6 years
    Worked like a charm!
  • vntstudy
    vntstudy about 6 years
    While setting fragment on container. My action bar is getting hide.