How to Use Drawerlayout to Display Over the Actionbar/Toolbar and Under the Status Bar

How do I use DrawerLayout to display over the ActionBar/Toolbar and under the status bar?

New functionality in the framework and support libs allow exactly this. There are three 'pieces of the puzzle':

  1. Using Toolbar so that you can embed your action bar into your view hierarchy.
  2. Making DrawerLayout fitsSystemWindows so that it is layed out behind the system bars.
  3. Disabling Theme.Material's normal status bar coloring so that DrawerLayout can draw there instead.

I'll assume that you will use the new appcompat.

First, your layout should look like this:

<!-- The important thing to note here is the added fitSystemWindows -->
<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"
android:fitsSystemWindows="true">

<!-- Your normal content view -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<!-- We use a Toolbar so that our drawer can be displayed
in front of the action bar -->
<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" />

<!-- The rest of your content view -->

</LinearLayout>

<!-- Your drawer view. This can be any view, LinearLayout
is just an example. As we have set fitSystemWindows=true
this will be displayed under the status bar. -->
<LinearLayout
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="left|start"
android:fitsSystemWindows="true">

<!-- Your drawer content -->

</LinearLayout>

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

Then in your Activity/Fragment:

public void onCreate(Bundled savedInstanceState) {
super.onCreate(savedInstanceState);

// Your normal setup. Blah blah ...

// As we're using a Toolbar, we should retrieve it and set it
// to be our ActionBar
Toolbar toolbar = (...) findViewById(R.id.my_awesome_toolbar);
setSupportActionBar(toolbar);

// Now retrieve the DrawerLayout so that we can set the status bar color.
// This only takes effect on Lollipop, or when using translucentStatusBar
// on KitKat.
DrawerLayout drawerLayout = (...) findViewById(R.id.my_drawer_layout);
drawerLayout.setStatusBarBackgroundColor(yourChosenColor);
}

Then you need to make sure that the DrawerLayout is visible behind the status bar. You do that by changing your values-v21 theme:

values-v21/themes.xml

<style name="Theme.MyApp" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentStatus">true</item>
</style>

Note:
If a <fragment android:name="fragments.NavigationDrawerFragment"> is used instead of

<LinearLayout
android:layout_width="304dp"
android:layout_height="match_parent"
android:layout_gravity="left|start"
android:fitsSystemWindows="true">

<!-- Your drawer content -->

</LinearLayout>

the actual layout, the desired effect will be achieved if you call fitsSystemWindows(boolean) on a view that you return from onCreateView method.

@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View mDrawerListView = inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
mDrawerListView.setFitsSystemWindows(true);
return mDrawerListView;
}

Navigation Drawer on the top of ActionBar / StatusBar like Android 5.0 without using AppCompact / ToolBar

In a regular Activity, the ActionBar is part of an overlay View that is the only direct child of the Window's DecorView. You can remove this child from the DecorView, inflate the activity_main main layout into the DecorView, and then add the overlay View to the DrawerLayout's FrameLayout, effectively putting the drawer on top of everything.

In order to avoid making changes to the BaseLogeableActivity class, we'll need to change the ID of the DrawerLayout's FrameLayout, and ensure a Resource ID of container exists to assign to the dynamically created FrameLayout that will hold the Fragments.

Create the Resource ID of container, if necessary:

<item type="id" name="container" />

Change the ID of the main layout's FrameLayout:

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

The cleanest way to add the View juggling code is probably to just override MainActivity's setContentView() method, like so:

@Override
public void setContentView(int layoutResID) {
ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
View overlayView = decorView.getChildAt(0);

decorView.removeView(overlayView);
getLayoutInflater().inflate(layoutResID, decorView, true);

FrameLayout overlayContainer = (FrameLayout) findViewById(R.id.overlay_container);
overlayContainer.addView(overlayView);

FrameLayout container = new FrameLayout(this);
container.setId(R.id.container);

ViewGroup content = (ViewGroup) overlayView.findViewById(android.R.id.content);
content.addView(container);
}

And finally, if you want your Activity to cover the Status Bar, add the following attribute setting to its theme:

<item name="android:windowFullscreen">true</item>

Or, since you can't change the theme, call the following before the setContentView() call:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);

How do I make DrawerLayout to display below the Toolbar?

<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">

<!-- 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">

<!-- drawer content -->

</LinearLayout>

<!-- normal content view -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">



<!-- The rest of content view -->

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

</LinearLayout>

DrawerLayout - Opaque Status Bar Over Drawer and Translucent Status Bar Over Container

After more searching on SO I found this answer that although didn't directly solve my problem, it gave me clues as to what was going on. In order to enable the translucent status bar in the fragment I needed to change the container layout to a CoordinatorLayout.

Furthermore, I needed to add "fitsSystemWindows=true" to all child views in order for the inset to be placed correctly in my desired fragment.

Here's the updated code that gave me the desired result:

activity_main.xml

<?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="start"
android:fitsSystemWindows="true">

<android.support.design.widget.CoordinatorLayout
android:fitsSystemWindows="true"
android:id="@+id/main_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.design.widget.CoordinatorLayout>

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

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

fragment_profile.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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<android.support.design.widget.AppBarLayout
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<android.support.design.widget.CollapsingToolbarLayout
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways">

<RelativeLayout
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<android.support.v7.widget.CardView
android:id="@+id/card_cover"
android:layout_width="match_parent"
android:layout_height="200dp"
app:cardElevation="10dp">

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#11b4ff"
android:src="@android:drawable/sym_def_app_icon"/>
</android.support.v7.widget.CardView>

<android.support.v7.widget.CardView
android:id="@+id/card_profile"
android:layout_below="@id/card_cover"
android:layout_width="120dp"
android:layout_height="120dp"
app:cardElevation="10dp"
android:layout_marginLeft="15dp"
android:layout_marginBottom="15dp"
android:layout_marginTop="-60dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#1119ff"
android:src="@android:drawable/sym_def_app_icon"
/>
</android.support.v7.widget.CardView>

<TextView
android:layout_margin="15dp"
android:layout_below="@id/card_cover"
android:layout_toRightOf="@id/card_profile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Profile Name"
android:textSize="30sp"/>

</RelativeLayout>

<android.support.v7.widget.Toolbar
android:id="@+id/fragment_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

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

<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:tabIndicatorColor="@android:color/white"
app:tabIndicatorHeight="6dp"
app:tabMode="scrollable"
app:tabSelectedTextColor="@android:color/white"
app:tabTextColor="@android:color/white"/>

</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>

How to add DrawerLayout to my ToolBar / ActionBar

You can use something like this:

    Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(
this, mDrawerLayout, mToolbar,
R.string.navigation_drawer_open, R.string.navigation_drawer_close
);
mDrawerLayout.setDrawerListener(mDrawerToggle);

mDrawerToggle.syncState();

Pay attention.
android.support.v4.app.ActionBarDrawerToggle is deprecated.

You have to use the android.support.v7.app.ActionBarDrawerToggle.
This class has a constructor with the Toolbar.

Cannot put DrawerLayout under StatusBar

Sample Image

  1. add to your onCreate() of Activity

        getWindow().getDecorView().setSystemUiVisibility(
    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
  2. Change ScrimInsetsFrameLayout's android:fitsSystemWindows property to false

  3. Remove android:fitsSystemWindows="true" from DrawerLayout

    <android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:id="@+id/drawer"
    android:background="@drawable/background"> <!--png image-->

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

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

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

    </FrameLayout>

    </FrameLayout>

    <com.example.myapplication.ScrimInsetsFrameLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/linearLayout"
    android:layout_width="304dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="false"
    app:insetForeground="#4000"
    android:clickable="true"
    android:background="#ffffff"> .....

    </com.example.myapplication.ScrimInsetsFrameLayout>

    </android.support.v4.widget.DrawerLayout>
  4. Add these styles into your AppTheme_Activities Theme (keeping your status desired color):

            <item name="windowActionBarOverlay">false</item>
    <item name="android:windowActionBarOverlay">false</item>
    <item name="android:fitsSystemWindows">false</item>
    <item name="android:statusBarColor">#4000</item>
  5. This will to the state, that Toolbar gets under the StatusBar too, so you'll need to do this hack:

    • Make Toolbar's height = "wrap_content"

      <android.support.v7.widget.Toolbar
      android:id="@+id/toolbar"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="?attr/colorPrimary"
      app:popupTheme="@style/AppTheme.PopupOverlay" />
    • Set Padding for the Toolbar:

      Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
      setSupportActionBar(toolbar);
      toolbar.setPadding(0, getStatusBarHeight(), 0, 0);
      ......
      ......
      public int getStatusBarHeight() {
      int result = 0;

      if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
      int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
      if (resourceId > 0) {
      result = getResources().getDimensionPixelSize(resourceId);
      }
      }
      return result;
      }

That's should be it!

I've uploaded the source code of the test-application with Navigation Drawer below the status bar to my dropbox - feel free to check it out.

I have answered pretty similar question a while ago - maybe you will also find it useful: Translucent StatusBar with dynamic ActionBar color in Android

I hope, it helps

Material design drawer under the status bar: how to achieve it using a DrawerLayout with two FrameLayouts as children?

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

<LinearLayout
android:id="@+id/someLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<android.support.v7.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />
<FrameLayout android:id="@+id/container"></FrameLayout>

</LinearLayout>

<com.myapp.widget.ScrimInsetsFrameLayout
android:id="@+id/navigation_drawer"
android:layout_width="@dimen/navdrawer_width"/>
</android.support.v4.widget.DrawerLayout>

Now you just have to change your fragments in R.id.container, because container is under ToolBar in someLayout LinearLayout

I ommited some args of layouts but that is not the point.



Related Topics



Leave a reply



Submit