PLEASE NOTE: This answer was originally written when Android 4.4 (KitKat) was still fairly new. Starting with Android 5.0 and especially because of the introduction of ToolBar this answer cannot be considered relevant anymore! But from a technical point of view, for those of you who want to know about the internal workings of Android, this answer can still be of great value!
NavigationDrawer was specifically designed to be placed below the ActionBar , and there is no way to implement NavigationDrawer to make the ActionBar move with it - unless perhaps looking for the View that makes up the ActionBar and animating it along with the NavigationDrawer , but I would never recommend something like that because it would be difficult and error prone. In my opinion, you have only two options:
Since you said you did not want to use a library that implements a custom sliding menu, this is your only option, fortunately, it really is not as difficult as soon as you know how to do it.
1) The main explanation
You can move all the content of an Activity β I mean everything, including an ActionBar β by placing a marker or pad on the View that makes up the Activity . This View is the parent of the View with id android.R.id.content :
View content = (View) activity.findViewById(android.R.id.content).getParent();
In Honeycomb (Android version 3.0 - API level 11) or higher - in other words, after the ActionBar been introduced - you need to use the fields to change the position of Activities , and in previous versions you need to use indents, To simplify this, I recommend creating helper methods that perform the correct actions for each level of the API. First, consider how to set the position of an Activity :
public void setActivityPosition(int x, int y) { // With this if statement we can check if the devices API level is above Honeycomb or below if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // On Honeycomb or abvoe we set a margin FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams(); contentParams.setMargins(x, y, -x, -y); this.content.setLayoutParams(contentParams); } else { // And on devices below Honeycomb we set a padding this.content.setPadding(x, y, -x, -y); } }
Please note that in both cases there is a negative margin or negative complement on opposite sides. This significantly increases the size of the Activity beyond its normal boundaries. This prevents the actual size of the Activity from changing when we move it somewhere.
We also need two methods to get the current position of the Activity . One for position x, one for position y:
public int getActivityPositionX() { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // On Honeycomb or above we return the left margin FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams(); return contentParams.leftMargin; } else { // On devices below Honeycomb we return the left padding return this.content.getPaddingLeft(); } } public int getActivityPositionY() { if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // On Honeycomb or above we return the top margin FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams(); return contentParams.topMargin; } else { // On devices below Honeycomb we return the top padding return this.content.getPaddingTop(); } }
It is also very simple to add animation. The only important thing here is a little math to bring it back to life from its previous position to its new position.
// We get the current position of the Activity final int currentX = getActivityPositionX(); final int currentY = getActivityPositionY(); // The new position is set setActivityPosition(x, y); // We animate the Activity to slide from its previous position to its new position TranslateAnimation animation = new TranslateAnimation(currentX - x, 0, currentY - y, 0); animation.setDuration(500); this.content.startAnimation(animation);
You can display the View in the location that opens by shifting the Activity by adding it to the parent View element:
final int currentX = getActivityPositionX(); FrameLayout menuContainer = new FrameLayout(context);
And thatβs almost all you need to create a basic sliding menu that works on most, if not all devices above Eclair (Android 2.1 - Level 7 API).
2) Animation Activity
The first part of creating a sliding menu is to move the Activity to the side. Therefore, we must first try to move the Activity as follows:

To create this, we just need to add the code above:
import android.os.Build; import android.support.v4.app.FragmentActivity; import android.view.View; import android.view.animation.TranslateAnimation; import android.widget.FrameLayout; public class ActivitySlider { private final FragmentActivity activity; private final View content; public ActivitySlider(FragmentActivity activity) { this.activity = activity; // Here we get the content View from the Activity. this.content = (View) activity.findViewById(android.R.id.content).getParent(); } public void slideTo(int x, int y) { // We get the current position of the Activity final int currentX = getActivityPositionX(); final int currentY = getActivityPositionY(); // The new position is set setActivityPosition(x, y); // We animate the Activity to slide from its previous position to its new position TranslateAnimation animation = new TranslateAnimation(currentX - x, 0, currentY - y, 0); animation.setDuration(500); this.content.startAnimation(animation); } public void setActivityPosition(int x, int y) { // With this if statement we can check if the devices API level is above Honeycomb or below if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // On Honeycomb or above we set a margin FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams(); contentParams.setMargins(x, y, -x, -y); this.content.setLayoutParams(contentParams); } else { // And on devices below Honeycomb we set a padding this.content.setPadding(x, y, -x, -y); } } public int getActivityPositionX() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // On Honeycomb or above we return the left margin FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams(); return contentParams.leftMargin; } else { // On devices below Honeycomb we return the left padding return this.content.getPaddingLeft(); } } public int getActivityPositionY() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // On Honeycomb or above we return the top margin FrameLayout.LayoutParams contentParams = (FrameLayout.LayoutParams) this.content.getLayoutParams(); return contentParams.topMargin; } else { // On devices below Honeycomb we return the top padding return this.content.getPaddingTop(); } } }
You can use the ActivitySlider class as follows:
ActivitySlider slider = new ActivitySlider(activity);
3) Adding a sliding menu
Now we want to open the menu when the Activity is deleted as follows: 
As you can see, this also pushes the ActionBar to the side.
The ActivitySlider class does not need to be modified in order to create a sliding menu, basically we just add two methods: showMenu() and hideMenu() . I will follow best practices and use Fragment as a sliding menu. The first thing we need is a View - for example, FrameLayout - as a container for our Fragment . We need to add this View to the parent element of the View Activity :
Since we set the visibility of the View container to VISIBLE only when the sliding menu is actually open, we can use the following method to check if the menu is open or closed:
public boolean isMenuVisible() { return this.menuContainer.getVisibility() == View.VISIBLE; }
To set the Fragment menu, we add the setter method, which executes the FragmentTransaction and adds the Fragment menu to the FrameLayout :
public void setMenuFragment(Fragment fragment) { FragmentManager manager = this.activity.getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); transaction.replace(R.id.flMenuContainer, fragment); transaction.commit(); }
I also tend to add a second setter, which for convenience creates a Fragment from Class :
public <T extends Fragment> void setMenuFragment(Class<T> cls) { Fragment fragment = Fragment.instantiate(this.activity, cls.getName()); setMenuFragment(fragment); }
There is another important thing to keep in mind when it comes to the Fragment menu. We work much further in the View hierarchy than usual. Therefore, we must take into account such things as the height of the status bar. If we did not take this into account at the top of the Fragment menu, we would be hidden behind the status bar. You can get the height of the status bar as follows:
Rect rectangle = new Rect(); Window window = this.activity.getWindow(); window.getDecorView().getWindowVisibleDisplayFrame(rectangle); final int statusBarHeight = rectangle.top;
We must put the top margin in the View container of the Fragment menu as follows:
Finally, we can put it all together:
import android.graphics.Rect; import android.os.Build; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.widget.FrameLayout; import at.test.app.R; import at.test.app.helper.LayoutHelper; public class ActivitySlider { private final FragmentActivity activity; private final View content; private final FrameLayout menuContainer; public ActivitySlider(FragmentActivity activity) { this.activity = activity;
I am using the static helper method in showMenu() to convert dip to pixels. Here is the code for this method:
public static int dpToPixel(Context context, int dp) { float scale = getDisplayDensityFactor(context); return (int) (dp * scale + 0.5f); } private static float getDisplayDensityFactor(Context context) { if (context != null) { Resources res = context.getResources(); if (res != null) { DisplayMetrics metrics = res.getDisplayMetrics(); if(metrics != null) { return metrics.density; } } } return 1.0f; }
You can use this new version of the ActivitySlider class as follows:
ActivitySlider slider = new ActivitySlider(activity); slider.setMenuFragment(MenuFragment.class);
4) Conclusion and testing
Doing something like this is surprisingly easy when you know that you can just put a margin or addition on the View in the Activity . But the difficulty is getting it to work on many different devices. Implementations can change dramatically at several levels of the API and can have a significant impact on how this behaves. Having said that, any code I wrote here should work on most, if not all devices above Eclair (Android 2.1 - API level 7) without problems.
Of course, the solution I posted here is not complete, it can use a little extra polishing and cleaning, so feel free to refine the code to suit your needs.
I tested everything on the following devices:
HTC
- One M8 (Android 4.4.2 - KitKat): Works
- Sensation (Android 4.0.3 - Ice Cream Sandwich): Work
- Desire (Android 2.3.3 - Gingerbread): Works
- One (Android 4.4.2 - KitKat): Working
Samsung
- Galaxy S3 Mini (Android 4.1.2 - Bean Jelly): Working
- Galaxy S4 Mini (Android 4.2.2 - Jelly Bean): Working
- Galaxy S4 (Android 4.4.2 - KitKat): Works
- Galaxy S5 (Android 4.4.2 - KitKat): Working
- Galaxy S Plus (Android 2.3.3 - Gingerbread): Work
- Galaxy Ace (Android 2.3.6 - Gingerbread): Working
- Galaxy S2 (Android 4.1.2 - Bean Jelly): Work
- Galaxy S3 (Android 4.3 - Jelly Bean): Works
- Galaxy Note 2 (Android 4.3 - Jelly Bean): Work
- Galaxy Nexus (Android 4.2.1 - Jelly Bean): Work
Motorola
- Moto G (Android 4.4.2 - KitKat): Work
LG
- Nexus 5 (Android 4.4.2 - KitKat): Works
Zte
- Blade (Android 2.1 - Eclair): Works
I hope I can help you, and if you have any further questions or anything else incomprehensible, do not hesitate to ask!