Same Navigation Drawer in different Activities
Asked Answered
B

13

212

I made a working navigation drawer like it's shown in the tutorial on the developer.android.com website. But now, I want to use one Navigation Drawer, i created in the NavigationDrawer.class for multiple Activities in my Application.

My question is, if anyone here can make a little Tutorial, which explains, how to use one Navigation drawer for multiple Activities.

I read it first at this Answer Android Navigation Drawer on multiple Activities

but it didn't work on my Project

public class NavigationDrawer extends Activity {
public DrawerLayout drawerLayout;
public ListView drawerList;
private ActionBarDrawerToggle drawerToggle;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout, R.drawable.ic_drawer, 0, 0) {

        public void onDrawerClosed(View view) {
            getActionBar().setTitle(R.string.app_name);
        }

        public void onDrawerOpened(View drawerView) {
            getActionBar().setTitle(R.string.menu);
        }
    };
    drawerLayout.setDrawerListener(drawerToggle);

    getActionBar().setDisplayHomeAsUpEnabled(true);
    getActionBar().setHomeButtonEnabled(true);

    listItems = getResources().getStringArray(R.array.layers_array);
    drawerList = (ListView) findViewById(R.id.left_drawer);
    drawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, android.R.id.text,
            listItems));
    
    drawerList.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
            drawerClickEvent(pos);
        }
    });
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (drawerToggle.onOptionsItemSelected(item)) {
        return true;
    }
    return super.onOptionsItemSelected(item);

}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    drawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    drawerToggle.onConfigurationChanged(newConfig);
}
}

In this Activity i want to have the Navigation Drawer so I extends 'NavigationDrawer' and in some other Activities i want to User the Same Navigation drawer

  public class SampleActivity extends NavigationDrawer {...}
Bozarth answered 18/10, 2013 at 14:7 Comment(2)
You can find the examples here.Buyse
you can find from : #33009969Galton
G
189

If you want a navigation drawer, you should use fragments. I followed this tutorial last week and it works great:

http://developer.android.com/training/implementing-navigation/nav-drawer.html

You can also download sample code from this tutorial, to see how you can do this.


Without fragments:

This is your BaseActivity Code:

public class BaseActivity extends Activity
{
    public DrawerLayout drawerLayout;
    public ListView drawerList;
    public String[] layers;
    private ActionBarDrawerToggle drawerToggle;
    private Map map;
    
    protected void onCreate(Bundle savedInstanceState)
    {
        // R.id.drawer_layout should be in every activity with exactly the same id.
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        
        drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout, R.drawable.ic_drawer, 0, 0) 
        {
            public void onDrawerClosed(View view) 
            {
                getActionBar().setTitle(R.string.app_name);
            }
    
            public void onDrawerOpened(View drawerView) 
            {
                getActionBar().setTitle(R.string.menu);
            }
        };
        drawerLayout.setDrawerListener(drawerToggle);
    
        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);
        
        layers = getResources().getStringArray(R.array.layers_array);
        drawerList = (ListView) findViewById(R.id.left_drawer);
        View header = getLayoutInflater().inflate(R.layout.drawer_list_header, null);
        drawerList.addHeaderView(header, null, false);
        drawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, android.R.id.text1,
                layers));
        View footerView = ((LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
                R.layout.drawer_list_footer, null, false);
        drawerList.addFooterView(footerView);
    
        drawerList.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
                map.drawerClickEvent(pos);
            }
        });
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
        if (drawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    
    }
    
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggle.syncState();
    }
    
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }
}

All the other Activities that needs to have a navigation drawer should extend this Activity instead of Activity itself, example:

public class AnyActivity extends BaseActivity
{
    //Because this activity extends BaseActivity it automatically has the navigation drawer
    //You can just write your normal Activity code and you don't need to add anything for the navigation drawer
}

XML

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <!-- Put what you want as your normal screen in here, you can also choose for a linear layout or any other layout, whatever you prefer -->
    </FrameLayout>
    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111"/>
</android.support.v4.widget.DrawerLayout>

Edit:

I experienced some difficulties myself, so here is a solution if you get NullPointerExceptions. In BaseActivity change the onCreate function to protected void onCreateDrawer(). The rest can stay the same. In the Activities which extend BaseActivity put the code in this order:

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity);
    super.onCreateDrawer();

This is how you can create a navigation drawer with multiple activities, if you have any questions feel free to ask.


Edit 2:

As said by @GregDan your BaseActivity can also override setContentView() and call onCreateDrawer there:

@Override 
public void setContentView(@LayoutRes int layoutResID) 
{ 
    super.setContentView(layoutResID); 
    onCreateDrawer() ;
}
Gambier answered 18/10, 2013 at 14:12 Comment(66)
I Made a working Navigation drawer, but now I want to Use one Navigation drawer in multiple activitiesBozarth
The way to go is to use fragments instead of activities. I can't think of any reason why you want to use activities over fragments.Gambier
I don't want to use activitys over fragments, I just want to use different activitys which uses all the same navigation drawer. I want activity, because there I can use different types of layout like swipe view, map view...Bozarth
Having just one Activity can be a daunting task for any fairly complex app. Using Activities gives you a lot of free things from the system - so it is a valid point how to use multiple Activities. I can't imagine one Activity handling communication between any number of fragment combinations - it's just not gonna work.Ref
I'm sorry it took so long for me to answer. I Edited my answer. I believe this is the tutorial you were looking for. Hope this helps.Gambier
do not know why this answer was accepted but extending main class does not do the task. It does not slide out.Castroprauxel
@RishabhSrivastava I don´t know what you did, but you did something wrong. This worked for me and for Mex and probably more people. Did you follow my tutorial correctly? You have to write an activity class: BaseActivity. And the Activity classes you want in your app need to extend BaseActivity. Thats all there is to it.Gambier
Ok it worked but the list set in the baseactivity does not show up here in AnyActivity....why?Castroprauxel
Make a new question and link me to it. I need to see your code.Gambier
@KevinvanMierlo can you tell me what you mean by: R.id.drawer_layout should be in every activity with exactly the same id. Because I did exactly what you told here and I get a NullPointerException in onCreate() method of the Activity that extends this BaseActivity..Pulchi
@Pulchi You make a drawerlayout in the layout file of your activity and you give this the id "drawer_layout"Gambier
@KevinvanMierlo I do exactly that and I think it should work now, but it doesn't. When I click on the drawer icon the drawer does not show. I don't get any errors whatsoever. Do you know why?Pulchi
@KevinvanMierlo btw, I think you forgot these 2 lines? super.onCreate(savedInstanceState); setContentView(R.layout.activity_base);Pulchi
@KevinvanMierlo how do I keep the layout of my activity and add this drawerLayout into that? Because both activities require me to set a contentView.. And the layout of my activity overrides the layout of the drawer. Can you explain that part please?Pulchi
OK, create a new question and link that question to me or put your code online and link that to me. I don't know whats not working untill I see your code.Gambier
@KevinvanMierlo How can i move from one activity to another while i click the item in Drawer listParaphernalia
@Paraphernalia set setOnItemClickListener on drawerList and from there start your new activity (Intent myIntent = new Intent(CurrentActivity.this, NextActivity.class); CurrentActivity.this.startActivity(myIntent);)Gambier
Hi Kevin, I've followed your instructions and it's crashing. I've posted a question, I'd appreciate a lot if you could help me out! :) #22137783Arianna
What if you are extending a fragmentActivity for a viewpager already, how do you go about implementing this... I was originally just including the same code in both my Home activity and my other activity, the problem is that from my other activity with the viewpager I could not click on any items - is that an issue that can be fixed or try to use this method but in that case how to implement it?Borlase
@Borlase I think if you want that your base activity needs to extend fragmentActivity or else nothing will work. For the rest I'm not sure if something could cause issues. If you still have issues, make a question and link me to it, cause then I need to see some code.Gambier
@Ref I am trying to do just that, a single activity architecture. I definitely feel that I am getting bogged down. The dilemma, though, is that fragments load in so much faster than launching new activities.Superb
Loads faster than launching new activities ??? - You must be doing something wrong. Any activity should start instantly and then you do the heavy lifting using background tasks while showing a spinner or whatever makes sense for your app. I've made countless apps and never had problems with slow activities.Ref
@KevinvanMierlo : Just a quesiotn, for implementing navigation drawer as i understood - Am i supposed to have only one activity and all other as fragments in my whole app ?Cheep
@ShumailMohy-ud-Din That is recommended by google. But as slott said, if you have a complex app this might not be the right way. For smaller apps one activity and only fragments should be fine.Gambier
@KevinvanMierlo Thankyou - Yeah for complex that's seriously a mess. I am trying to do with activitiesCheep
@KevinvanMierlo Can you please post the XML layout for BaseActivity and AnyActivity? That would be very helpful!Turgid
@user87049 XML layout added. BaseActivity doesn't have a layout. Just make sure to add drawer_layout in every activity and extend BaseActivity in every Activity.Gambier
Can we make it without the same XML in every Activity layout?Dakota
@Dakota Yeah, the drawer layout part and the listview part should be in every activity. The framelayout can be any layout you want and this is the layout for your screen. You can change this in the way you likeGambier
@KevinvanMierlo I'm using Android Studio and pasted the BaseActivity code, but am running up against symbols not being able to be resolved such as ic_drawer, menu, layers_array, drawer_list_header, drawer_list_item, drawer_list_footer, and the drawerClickEvent() as well If the BaseActivity doesn't require a layout how do I resolve these errors?Madrigalist
@KurtWagner This BaseActivity was specific for the question, here is the code for everybody to use: gist.github.com/kevinvanmierlo/c1a0d6b8bed65b1eeaa6 ic_drawer is an icon provided in the actionbar pack: developer.android.com/downloads/design/Android_Design_Icons_20130926.zip (ic_drawer is the image, three stripes, next to the logo if a navigation drawer is available)Gambier
@KevinvanMierlo drawer layout is appering only by dragging.. on click image is not working... and list is not visible.Authority
@MSGadag I'm not sure why list is not visible, but for the on click image check this: developer.android.com/training/implementing-navigation/… This is from the android website that walks you through how to get the on click on a drawerlayout. If you can't manage to make the list working create a new question and link me to that question, I will help youGambier
@Ref I don't agree with you. this is not about communication between activities. this is inheritance. all of activities and it's components even naviagation drawer is alive but with a same parent.Biomass
@KevinvanMierlo Can you please post snippet of main_activity.xml too? Thanks!Suppository
@HamedMP The xml is the post snippet of main_activity.xml. In the FrameLayout (content_frame) you put your normal layout. I just stripped that because it's irrelevant for the answer. Just to be clear, the BaseActivity doesn't have an xml file.Gambier
Better solution is to @Override public void setContentView(@LayoutRes int layoutResID) { super.setContentView(layoutResID); onCreateDrawer() }Ur
@GregDan Good solution! Added it to my answer.Gambier
It works good.I have a doubt.Actually should we add drawer layout and listview in the child activity's layout also?Tinhorn
@Sharanth yes those layouts should be added to the child activity. You could put the list view in a separate layout or make the drawer a fragment so you don't have to add everything everything you want an activity with a drawerGambier
@Ref You can use EventBus for all your communications.Ruy
Yes EventBus is a real game changer when it comes to communication across fragments and activities.Ref
I try to use this solution but I have a problem on this line: drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout, R.drawable.ic_drawer, 0, 0) where AS says it is specting a toolbar on the third parameter and R.drawable.ic_drawer is an int. How can I solve it?Toothed
@PauArlandisMartinez The new ActionBarDrawerToggle doesn't need a drawable anymore, so you have two options: Use the ActionBarDrawerToggle with an ActionBar or with a Toolbar. Example using ActionBar: drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, 0, 0);. Example with Toolbar: drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, 0, 0);. The two zeros on the end should be a String located in the strings.xml.Gambier
@KevinvanMierlo ok, but if I use the actionBar solution I need to import android.support.v4.app.ActionBarDrawerToggle and If I use the toolbar solution I need to import android.support.v7.app.ActionBarDrawerToggle. It's important to have this in mind. Also the actionBar solution is deprecated today.Toothed
@PauArlandisMartinez No you should use android.support.v7.app.ActionBarDrawerToggle. You can leave out toolbar and I think it should work then. But the ActionBar in general is deprecated now, so you should think about the Toolbar solution.Gambier
sir, i used the same with extending BaseActivity but on back pressed this navigation doesn't work. Please helpOresund
@PriyankaMinhas Can you create a new question? I don't want to overload this answer with comments. In that question you could give me some more details and the code you're using.Gambier
Here is it - #37025408Oresund
@KevinvanMierlo I get null pointer exceptions when the onCreateDrawer method tries to operate on the drawer. Because the drawer xml is in the layout of the base activity (dashboard activity in my case), it isn't available in subsequent activities extending the base activity. How should the XML be arranged? I was going to abstract the drawer into a separate layout file but based on how the drawer needs to wrap the rest of the content I'm not sure how to accomplish that.Pinnatifid
@KevinvanMierlo I created a separate question here: #39878880Pinnatifid
Where are you using content_frame?Sempach
@Sempach content_frame is the regular layout you normally put the screen in. So if you want to show an image on that page you need to put the ImageView inside the content_frame. It could also be another layout, it's just to clarify that the regular layout should be there.Gambier
After many bugs and difficult situations with fragments I understood that it should better use activities with Navigation drawer. Keyboard events, transparent statusbar, data transfer between fragments and so on. Don't use fragments!Moran
Some people write that activity with fragments creates new fragments faster, also an animation is more friendly (with activities you should create a new activity and then close a drawer). Also I encountered a difficult bug with creating and managing menus. Then I returned to fragments, as they already work :(Moran
@Moran You're right that fragments responds quicker and has more possibilities with animation. But in the end, if you create this code once you can reüse it for every project you have with a NavigationDrawer. Creating menus should be the same as alwaysGambier
@KevinvanMierlo, thanks. First I tried to make with fragments as recommended, but I need different toolbars at different fragments ((a) usual ActionBars and (b) an image from top, behind transparent Statusbar). A similar topic: #35015682. I made one activity with DrawerLayout and NavigationView, having Toolbar and other stuff in fragment. It works not always correctly, especially on new Androids.Moran
Then I tried to replace with activities and got a problem when tried to replace a toolbar. onCreateOptionsMenu stopped adding menu buttons, onOptionsItemSelected stopped to be called. So many difficult situations, that I returned to fragments again.Moran
@Moran If it does not always work correctly, I don't really know what's going on. You could create another question for that. onCreateOptionsMenu is probably not called because you haven't done setSupportActionBar with the Toolbar. If this isn't the case you should also create another question.Gambier
@KevinvanMierlo, you are right, better create another question. Also will try your code for activities creation. Thanks!Moran
Cannot resolve method protected void onCreateDrawer() in Base activity extend from ActivityMooring
@AshikAzeez You need to create this method yourself. In the first part of my answer you'll see all drawer related code in the onCreate, but because that gave exceptions I moved the code to a method onCreateDrawer().Gambier
@KevinvanMierlo i've place original content inside framelayout . now when i replace it with fragment its overlap to eachother . any workarround ?Oren
@TejasPandya I don't really know what you mean, but I guess you should replace the fragments so it doesn't overlap and also remove the original view (which is now inside your fragmentGambier
I found this awesome page for getting a Kotlin fragment solution going in a hurry. You just need to change fragmentManager to supportFragmentManager and add android:id="@+id/content_main" to the content_main.xml layout. All of the changes to the generated template are in onNavigationItemSelected(). You'll need to modify it to use the back stack. javaant.com/android-navigation-drawer-using-fragment-and-kotlin/…Pol
It's all true with just one BIG problem. Fragments suck in almost every way, especially how they slide in and out. Absolutely NO beauty and STABILITY in that process, a possibility for double-clicking the links, etc.Playtime
M
35

I've found the best implementation. It's in the Google I/O 2014 app.

They use the same approach as Kevin's. If you can abstract yourself from all unneeded stuff in I/O app, you could extract everything you need and it is assured by Google that it's a correct usage of navigation drawer pattern. Each activity optionally has a DrawerLayout as its main layout. The interesting part is how the navigation to other screens is done. It is implemented in BaseActivity like this:

private void goToNavDrawerItem(int item) {
        Intent intent;
        switch (item) {
            case NAVDRAWER_ITEM_MY_SCHEDULE:
                intent = new Intent(this, MyScheduleActivity.class);
                startActivity(intent);
                finish();
                break;

This differs from the common way of replacing current fragment by a fragment transaction. But the user doesn't spot a visual difference.

Myriammyriameter answered 23/10, 2014 at 11:17 Comment(5)
This ^ I cant figure out how they start new activities and it works flawlessly. It's a large app to work through.Rheims
@hitch.united That's because they use a lot of fragments and just a few activities.Earlearla
@hitch.united they probably override the animation of the activity with overridePendingTransitions.Adapter
is Loading fragments instead of subclassing activities?Detrital
Here's the file from October 2014: github.com/google/iosched/blob/…Mate
T
8

So this answer is a few years late but someone may appreciate it. Android has given us a new widget that makes using one navigation drawer with several activities easier.

android.support.design.widget.NavigationView is modular and has its own layout in the menu folder. The way that you use it is to wrap xml layouts the following way:

  1. Root Layout is a android.support.v4.widget.DrawerLayout that contains two children: an <include ... /> for the layout that is being wrapped (see 2) and a android.support.design.widget.NavigationView.

    <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="true"
        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" />
    

nav_header_main is just a LinearLayout with orientation = vertical for the header of your Navigation Drawar.

activity_main_drawer is a menu xml in your res/menu directory. It can contain items and groups of your choice. If you use the AndroidStudio Gallery the wizard will make a basic one for you and you can see what your options are.

  1. App bar layout is usually now a android.support.design.widget.CoordinatorLayout and this will include two children: a android.support.design.widget.AppBarLayout (which contains a android.support.v7.widget.Toolbar) and an <include ... > for your actual content (see 3).

    <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"
        tools:context="yourpackage.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>
    
    <include layout="@layout/content_main" />
    

  2. Content layout can be whatever layout you want. This is the layout that contains the main content of the activity (not including the navigation drawer or app bar).

Now, the cool thing about all of this is that you can wrap each activity in these two layouts but have your NavigationView (see step 1) always point to activity_main_drawer (or whatever). This means that you will have the same(*) Navigation Drawer on all activities.

  • They won't be the same instance of NavigationView but, to be fair, that wasn't possible even with the BaseActivity solution outlined above.
Troxell answered 6/10, 2017 at 22:33 Comment(6)
stackoverflow is cutting off some of the enclosing xml brackets but the important stuff is all there.Troxell
but how do you treat functionality like buttons? you must write the same code in every activity?Humoral
Yes, because these are separate instances. However, you can make a super class for your activities to extend and put that code there once.Troxell
@Troxell can you write an example about making a super class for our activities?Colonialism
public abstract class MyBaseActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { // implement the following: Override public boolean onNavigationItemSelected(@NonNull MenuItem item) {} } public class MyActivity extends MyBaseActivity {}Troxell
The formatting is all wrong in the comment section. Define a base class for yourself that extends Activity (in this case, AppCompatActivity) and then all of your regular activities should extend your new base activity. Essentially, you are inserting a class in between your activities and Android's activity class.Troxell
E
8

Easiest way to reuse a common Navigation drawer among a group of activities

app_base_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

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

    </FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/menu_test"
        />
</android.support.v4.widget.DrawerLayout>

AppBaseActivity.java

/*
* This is a simple and easy approach to reuse the same 
* navigation drawer on your other activities. Just create
* a base layout that conains a DrawerLayout, the 
* navigation drawer and a FrameLayout to hold your
* content view. All you have to do is to extend your 
* activities from this class to set that navigation 
* drawer. Happy hacking :)
* P.S: You don't need to declare this Activity in the 
* AndroidManifest.xml. This is just a base class.
*/
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

public abstract class AppBaseActivity extends AppCompatActivity implements MenuItem.OnMenuItemClickListener {
    private FrameLayout view_stub; //This is the framelayout to keep your content view
    private NavigationView navigation_view; // The new navigation view from Android Design Library. Can inflate menu resources. Easy
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    private Menu drawerMenu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.app_base_layout);// The base layout that contains your navigation drawer.
        view_stub = (FrameLayout) findViewById(R.id.view_stub);
        navigation_view = (NavigationView) findViewById(R.id.navigation_view);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, 0, 0);
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        drawerMenu = navigation_view.getMenu();
        for(int i = 0; i < drawerMenu.size(); i++) {
          drawerMenu.getItem(i).setOnMenuItemClickListener(this);
        }
        // and so on...
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    /* Override all setContentView methods to put the content view to the FrameLayout view_stub
     * so that, we can make other activity implementations looks like normal activity subclasses.
     */
    @Override
    public void setContentView(int layoutResID) {
        if (view_stub != null) {
            LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            View stubView = inflater.inflate(layoutResID, view_stub, false);
            view_stub.addView(stubView, lp);
        }
    }

    @Override
    public void setContentView(View view) {
        if (view_stub != null) {
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            view_stub.addView(view, lp);
        }
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        if (view_stub != null) {
            view_stub.addView(view, params);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        // Handle your other action bar items...

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.item1:
                // handle it
                break;
            case R.id.item2:
                // do whatever
                break;
            // and so on...
        }
        return false;
    }
}
Exuviate answered 9/2, 2018 at 16:16 Comment(2)
Can you provide an example of an activity that uses this base activity?Colonialism
Can't actually remember any details on this, I think just extending AppBaseActivity and setContentView ind default way should work.Exuviate
G
6

For anyone else looking to do what the original poster is asking, please consider to use fragments instead the way Kevin said. Here is an excellent tutorial on how to do that:

https://github.com/codepath/android_guides/wiki/Fragment-Navigation-Drawer

If you choose to instead use activities instead of fragments you are going to run into the problem of the nav drawer being re-created every time you navigate to a new activity. This results in an ugly/slow rendering of the nav drawer each time.

Glazier answered 3/2, 2016 at 8:28 Comment(0)
B
5

My suggestion is: do not use activities at all, instead use fragments, and replace them in the container (Linear Layout for example) where you show your first fragment. [Note: you can use this concept using the navigation graph. Compose further reduces the need to make your layout XMLs, so we can apply this there too.]

The code is available in Android Developer Tutorials, you just have to customize.

http://developer.android.com/training/implementing-navigation/nav-drawer.html

It is advisable that you should use more and more fragments in your application, and there should be only four basic activities local to your application, that you mention in your AndroidManifest.xml apart from the external ones (FacebookActivity for example):

  1. SplashActivity: uses no fragment, and uses FullScreen theme.

  2. LoginSignUpActivity: Do not require NavigationDrawer at all, and no back button as well, so simply use the normal toolbar, but at the least, 3 or 4 fragments will be required. Uses no-action-bar theme

  3. HomeActivity or DashBoard Activity: Uses no-action-bar theme. Here you require Navigation drawer, also all the screens that follow will be fragments or nested fragments, till the leaf view, with the shared drawer. All the settings, user profile and etc. will be here as fragments, in this activity. The fragments here will not be added to the back stack and will be opened from the drawer menu items. In the case of fragments that require back button instead of the drawer, there is a fourth kind of activity below.

  4. Activity without drawer. This activity has a back button on top and the fragments inside will be sharing the same action-bar. These fragments will be added to the back-stack, as there will be a navigation history.

[ For further guidance see: https://mcmap.net/q/128731/-how-to-set-font-custom-font-to-spinner-text-programmatically ]

Happy Coding !!

Broeder answered 4/3, 2014 at 5:50 Comment(4)
This is an older post. You can use fragments to ensure you have one activity always. You keep replacing the fragments in one container dedicated to it. Put in back stack when you need backward navigation, or pop all the fragments when you need a fragment to be shown as the first one.Broeder
@Cabuxa.Mapache Please check the attached link to my answer for getting further assistance. I have taken a common BaseActivity, which helps sharing ActionBar ToolBar and NavigatonDrawer and other components in all the fragments attached to it.Broeder
I was curious if you can give me on some input on the app I'm currently building and if what you mentioned above if i should do that in my app. please inbox me thank you.Footlight
Now that there is a navigation graph and actions (direction to other fragment or activity) concept making that even more easy for you. It supports child fragment for you. Now based on fragments having back button on top, full-screen, with navigation drawer or so, you may design the activities and put your navigation drawer reusing your fragments.Broeder
A
1

update this code in baseactivity. and dont forget to include drawer_list_header in your activity xml.

super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
setContentView(R.layout.drawer_list_header);

and dont use request() in your activity. but still the drawer is not visible on clicking image..and by dragging it will visible without list items. i tried a lot but no success. need some workouts for this...

Authority answered 8/11, 2014 at 10:1 Comment(0)
W
1

With @Kevin van Mierlo 's answer, you are also capable of implementing several drawers. For instance, the default menu located on the left side (start), and a further optional menu, located on the right side, which is only shown when determinate fragments are loaded.

I've been able to do that.

Warlike answered 28/11, 2014 at 10:26 Comment(0)
V
1
package xxxxxx;



import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.widget.SearchView;
import android.support.design.widget.NavigationView;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;


public class loginhome extends AppCompatActivity {
    private Toolbar toolbar;
    private NavigationView navigationView;
    private DrawerLayout drawerLayout;

    // Make sure to be using android.support.v7.app.ActionBarDrawerToggle version.
    // The android.support.v4.app.ActionBarDrawerToggle has been deprecated.
    private ActionBarDrawerToggle drawerToggle;

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

        // Initializing Toolbar and setting it as the actionbar
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


        //Initializing NavigationView


        navigationView = (NavigationView) findViewById(R.id.nav_view);

        //Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {

            // This method will trigger on item Click of navigation menu

            public boolean onNavigationItemSelected(MenuItem menuItem) {


                //Checking if the item is in checked state or not, if not make it in checked state
                if(menuItem.isChecked()) menuItem.setChecked(false);
                else menuItem.setChecked(true);

                //Closing drawer on item click
                drawerLayout.closeDrawers();

                //Check to see which item was being clicked and perform appropriate action
                switch (menuItem.getItemId()){


                    //Replacing the main content with ContentFragment Which is our Inbox View;
                    case R.id.nav_first_fragment:
                        Toast.makeText(getApplicationContext(),"First fragment",Toast.LENGTH_SHORT).show();
                         FirstFragment fragment = new FirstFragment();
                        android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
                        fragmentTransaction.replace(R.id.frame,fragment);
                        fragmentTransaction.commit();
                        return true;

                    // For rest of the options we just show a toast on click
                    case R.id.nav_second_fragment:
                        Toast.makeText(getApplicationContext(),"Second fragment",Toast.LENGTH_SHORT).show();
                        SecondFragment fragment2 = new SecondFragment();
                        android.support.v4.app.FragmentTransaction fragmentTransaction2 = getSupportFragmentManager().beginTransaction();
                        fragmentTransaction2.replace(R.id.frame,fragment2);
                        fragmentTransaction2.commit();
                        return true;

                    default:
                        Toast.makeText(getApplicationContext(),"Somethings Wrong",Toast.LENGTH_SHORT).show();
                        return true;

                }
            }
        });

        // Initializing Drawer Layout and ActionBarToggle
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.drawer_open, R.string.drawer_close){

            @Override
            public void onDrawerClosed(View drawerView) {
                // Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank
                super.onDrawerClosed(drawerView);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                // Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank

                super.onDrawerOpened(drawerView);
            }
        };

        //Setting the actionbarToggle to drawer layout
        drawerLayout.setDrawerListener(actionBarDrawerToggle);

        //calling sync state is necessay or else your hamburger icon wont show up
        actionBarDrawerToggle.syncState();







    }

use this for your toolbar.xml

<?xml version="1.0" encoding="utf-8"?>

    <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:elevation="4dp"
        android:id="@+id/toolbar"
        android:theme="@style/ThemeOverlay.AppCompat.Dark"


        >

    </android.support.v7.widget.Toolbar>

use this for navigation header if want to use

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:background="?attr/colorPrimaryDark"
    android:padding="16dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    android:orientation="vertical"
    android:gravity="bottom">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:id="@+id/navhead"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">

        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:textColor="#ffffff"
            android:text="tanya"
            android:textSize="14sp"
            android:textStyle="bold"

            />

        <TextView
            android:id="@+id/email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffff"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="5dp"
            android:text="tanya.com"
            android:textSize="14sp"
            android:textStyle="normal"

            />
    </LinearLayout>
    <de.hdodenhof.circleimageview.CircleImageView
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_below="@+id/imageView"
        android:layout_marginTop="15dp"

        android:src="@drawable/face"
        android:id="@+id/circleView"
        />



</RelativeLayout>
Vingtetun answered 3/3, 2017 at 13:23 Comment(0)
R
1

I do it in Kotlin like this:

open class BaseAppCompatActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

protected lateinit var drawerLayout: DrawerLayout
protected lateinit var navigationView: NavigationView
@Inject
lateinit var loginService: LoginService

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Log.d("BaseAppCompatActivity", "onCreate()")
    App.getComponent().inject(this)
    drawerLayout = findViewById(R.id.drawer_layout) as DrawerLayout

    val toolbar = findViewById(R.id.toolbar) as Toolbar
    setSupportActionBar(toolbar)

    navigationView = findViewById(R.id.nav_view) as NavigationView
    navigationView.setNavigationItemSelectedListener(this)

    val toggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)

    drawerLayout.addDrawerListener(toggle)
    toggle.syncState()
    toggle.isDrawerIndicatorEnabled = true

    val navigationViewHeaderView = navigationView.getHeaderView(0)
    navigationViewHeaderView.login_txt.text = SharedKey.username
}
private inline fun <reified T: Activity> launch():Boolean{
    if(this is T) return closeDrawer()
    val intent = Intent(applicationContext, T::class.java)
    startActivity(intent)
    finish()
    return true
}

private fun closeDrawer(): Boolean {
    drawerLayout.closeDrawer(GravityCompat.START)
    return true
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
    val id = item.itemId

    when (id) {
        R.id.action_tasks -> {
            return launch<TasksActivity>()
        }
        R.id.action_contacts -> {
            return launch<ContactActivity>()
        }
        R.id.action_logout -> {
            createExitDialog(loginService, this)
        }
    }
    return false
}
}

Activities for drawer must inherit this BaseAppCompatActivity, call super.onCreate after content is set (actually, can be moved to some init method) and have corresponding elements for ids in their layout

Ric answered 1/8, 2017 at 18:31 Comment(3)
I wanted to try your solution but I get this error: "This Activity already has an action bar supplied by the window decor". I want to switch between 3 activities and each other has its own app bar. Do you think that is possible ?Hairpin
I think, you need to move your actionbar to fragments in that case. In our app we used NoActionBar theme and provided toolbar for compatibility, as far as i remember.Ric
@Ric what would the code look like on the second activity? class trackActivity : BaseAppCompatActivity(){ ?Openhanded
F
1

My answer is just a conceptual one without any source code. It might be useful for some readers like myself to understand.

It depends on your initial approach on how you architecture your app. There are basically two approaches.

  1. You create one activity (base activity) and all the other views and screens will be fragments. That base activity contains the implementation for Drawer and Coordinator Layouts. It is actually my preferred way of doing because having small self-contained fragments will make app development easier and smoother.

  2. If you have started your app development with activities, one for each screen , then you will probably create base activity, and all other activity extends from it. The base activity will contain the code for drawer and coordinator implementation. Any activity that needs drawer implementation can extend from base activity.

I would personally prefer avoiding to use fragments and activities mixed without any organizing. That makes the development more difficult and get you stuck eventually. If you have done it, refactor your code.

Fonda answered 19/12, 2018 at 1:31 Comment(0)
G
0

It is elaborated in the following video tutorial

Navigation Drawer on Multiple Activities Using Base Activity

It is very easy to make a base navigation drawer activity and extend that base navigation drawer activity to all those activities on which you want to display navigation drawer,

  1. Make navigation menu, header
  2. create a base activity for navigation drawer
  3. create a content layout
  4. Combined menu, header, content layout on base activity
  5. By using frame layout, insert every activity in the drawer menu.

All steps are clearly explained in the video

Gerrilee answered 2/11, 2021 at 19:28 Comment(0)
A
-1

Create Navigation drawer in your MainActivity using fragment.
Initialize the Navigation Drawer in MainActivity
now in all other activities you want to use same Navigation Drawer put DrawerLayout as base and fragment as navigation drawer. Just set android:name in your fragment pointing to your fragment Java file. You won't need to initialize the fragment in other Activities.
You can access Nav Drawer by swipe in other activities like in Google Play Store app

Astraea answered 23/4, 2015 at 14:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.