52

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

Community
  • 1
  • 1
lemycanh
  • 827
  • 1
  • 11
  • 14

4 Answers4

51

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.

Peter Cai
  • 541
  • 5
  • 3
  • 3
    Confirmed this hack works as expected. We need to add padding to drawer, here is the trick to get status bar height: http://stackoverflow.com/questions/20584325/reliably-get-height-of-status-bar-to-solve-kitkat-translucent-navigation-issue. 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"); } – lemycanh Oct 04 '14 at 07:10
  • @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. – Peter Cai Oct 04 '14 at 07:15
  • great answer ! After implementing this, I realized that we are actually stealing a view from another layout and ditching it ! ha ha – uLYsseus Oct 26 '14 at 01:30
  • 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? – Mustafa Güven Nov 11 '14 at 13:21
  • 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? – Shubham A. Jul 21 '15 at 03:35
  • Worked like a charm! – dxpelou Jan 29 '18 at 17:08
  • While setting fragment on container. My action bar is getting hide. – vntstudy Mar 16 '18 at 12:09
34

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>
Richard Lindhout
  • 2,038
  • 2
  • 23
  • 38
  • You can use apktool to see the layout. It is bad but I have no way :( – lemycanh Apr 25 '14 at 13:52
  • 1
    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: https://github.com/google/iosched). The DrawerLayout can cover the action bar. – afollestad Aug 09 '14 at 05:14
  • At the time of the answer there weren't solutions like this I know! Thanks for your suggestion I edited the answer! – Richard Lindhout Aug 09 '14 at 09:39
1

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.
fupduck
  • 490
  • 4
  • 12
  • now saw that [here](https://stackoverflow.com/a/30998517/2347168) is the same answer but with more code. – fupduck Nov 28 '17 at 00:36
0

I have posted a trick that makes this possible in prior Android L versions. You can find my solution in this post. Hope it can be useful to someone.

Community
  • 1
  • 1
Andranik
  • 2,729
  • 1
  • 29
  • 45