Navigation Drawer to switch activities instead of fragments
Asked Answered
C

5

55

Is it possible to use a navigation drawer in android but instead of updating fragments, i would like to switch between activities as my means of navigation within the app.

Callis answered 18/10, 2013 at 5:39 Comment(6)
what exactly you want??Exist
What I want is to use a navigation drawer that would be available to all my activities to switch activities.Callis
Can you show me your design?? Why you want navigation drawer only??Exist
My initial design for my app is a dashboard navigation style but I am switching to navigation drawer style.Callis
There are other options also.. First define your requirement... may be other control can help you outExist
Did you checked this?? #16960998Exist
M
52

Yes it is possible - it's what I did for my app. I already had a number of activities set up, and rather than convert them all to fragments, I wanted to tailor the navigation drawer to work across all of them. Unfortunately, it's not a quick workaround, so if you have the option of using fragments, I would go with that. But regardless here's how I did it:

Let's say I have 2 activities, both of which I want to have the Navigation Drawer. In the layout.xml for each, I specified a DrawerLayout with the appropriate ListView to hold my navigation options. Essentially, the Navigation drawer is made every time I switch between activities, giving the appearance that it is persisting. To make life a lot easier, I took the common methods required to set up the navigation drawer and put them in their own class: NavigationDrawerSetup.java. That way my activities can use the same custom adapter, etc.

Within this NavigationDrawerSetup.java class, I have the following:

  • configureDrawer() - this sets up the ActionBar, ActionBarDrawerToggle, and the required listeners
  • My custom array adapter (to populate the navigation options within the list)
  • The selectOptions() method, which handles drawer item clicks

When you set up the navigation drawer within one of your activities, you just create a new NavigationDrawerSetup object and pass in the required layout parameters (like the DrawerLayout, ListView etc). Then you'd call configureDrawer():

        navigationDrawer = new NavigationDrawerSetup(mDrawerView, mDrawerLayout,
            mDrawerList, actionBar, mNavOptions, currentActivity);

    navigationDrawer.configureDrawer();

currentActivity is passed in since the navigation drawer is tied to the activity you are on. You will have to use it when you set up the ActionBarDrawerToggle:

mDrawerToggle = new ActionBarDrawerToggle(currentActivity, // host Activity
        mDrawerLayout, /* DrawerLayout object */
        R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
        R.string.drawer_open, /* "open drawer" description for accessibility */
        R.string.drawer_close /* "close drawer" description for accessibility */
        )

You will also need to use currentActivity when setting up your custom Adapter:

As for how to switch between activities via the navigation drawer, you can just set up new intents within your selectItem() method:

private void selectItem(int position) {

    // Handle Navigation Options
    Intent intent;
    switch (position) {
        case 0:
            intent = new Intent(currentActivity, NewActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            currentActivity.startActivity(intent);
            break;
        case 1: 
            // etc.
    }

Just make sure that your new Activity also has the navigation drawer setup and it should display.

There are a ton of things you can do to customize this method to your own needs, but this is the general structure of how I did it. Hope this helps!

Mors answered 18/10, 2013 at 19:11 Comment(6)
Will check this later as it seems like a pretty good suggestion. Maybe its very hard to emulate using the navigation drawer with fragments when it comes to the transition animation of a new fragment as going to a new activity looks different from loading a new fragment.Callis
@David Crozier you there ? i got stucked creating a navigation drawer , i can show you my code if you wantIsaiasisak
Is this solution actually recommended? I have done something similar and the UI is not behaving really smooth. The problem is that when you click one of the options in your NavigationDrawer then you have to hide the drawer and also start a new Activity. That transition looks a bit weird since both effects kind of overlap on the screen. Any suggestions?Rhynd
@AKh I "manage" the stack by finish()-ing the current activity after starting the new activity. This works for me, but not for you, if you want to preserve back stack across drawer selections.Cayenne
this seems like a much easier approach 👉 https://mcmap.net/q/339420/-navigation-drawer-to-switch-between-activitiesDung
this is not scaleable as the number of activities grows.Ibanez
E
18

You need a BaseDrawerActivity which implement the Navigation Drawer then extend the BaseDrawerActivity in each activity you need Navigation Drawer.

First create BaseDrawerActivity.java :

public class BaseDrawerActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{

    DrawerLayout drawerLayout;
    Toolbar toolbar;
    FrameLayout frameLayout;
    NavigationView navigationView;

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

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

        frameLayout = (FrameLayout) findViewById(R.id.content_frame);

        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawerLayout.setDrawerListener(toggle);
        toggle.syncState();

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

    @Override
    public void onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        int id = item.getItemId();

        //to prevent current item select over and over
        if (item.isChecked()){
            drawerLayout.closeDrawer(GravityCompat.START);
            return false;
        }

        if (id == R.id.nav_camera) {
            // Handle the camera action
            startActivity(new Intent(getApplicationContext(), CameraActivity.class));
        } else if (id == R.id.nav_gallery) {
            startActivity(new Intent(getApplicationContext(), GalleryActivity.class));
        } else if (id == R.id.nav_slideshow) {
            startActivity(new Intent(getApplicationContext(), SlideshowActivity.class));
        } else if (id == R.id.nav_manage) {
            startActivity(new Intent(getApplicationContext(), ManageActivity.class));
        } else if (id == R.id.nav_share) {
            startActivity(new Intent(getApplicationContext(), ShareActivity.class));
        } else if (id == R.id.nav_send) {
            startActivity(new Intent(getApplicationContext(), SendActivity.class));
        }
        drawerLayout.closeDrawer(GravityCompat.START);
        return true;
    }
}

then create activity_base_drawer.xml in res/layout folder:

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

    <include layout="@layout/app_bar_home"/>

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

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

where @layout/app_bar_home is:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

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

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

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

Next you enter your Activities that will have Navigation Drawer such as CameraActivity.java :

public class CameraActivity extends BaseDrawerActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getLayoutInflater().inflate(R.layout.activity_camera, frameLayout);

        /**
        * Setting title
        */
        setTitle("Camera");

    }

    @Override
    protected void onResume() {
        super.onResume();
        // to check current activity in the navigation drawer
        navigationView.getMenu().getItem(0).setChecked(true);
    }
}

Where R.layout.activity_camera is your layout for CameraActivity.java.

Then create other Activity like GalleryActivity.java and so on that will have Navigation Drawer:

public class GalleryActivity extends BaseDrawerActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getLayoutInflater().inflate(R.layout.activity_gallery, frameLayout);

        // Setting title
        setTitle("Gallery");

    }

    @Override
    protected void onResume() {
        super.onResume();
        navigationView.getMenu().getItem(1).setChecked(true);
    }
}
En answered 11/6, 2016 at 6:30 Comment(4)
How do you manage Activity stack... all the activities will be kept in stack. When you press back button, all the activities will close one by oneEloiseelon
how did you initialize frameLayout ? (regarding the line: getLayoutInflater().inflate(R.layout.activity_gallery, frameLayout);)Kamal
@YassirS frameLayout is in the BaseDrawerActivityCrary
One improvement to this answer. setContentView() can be overrided. https://mcmap.net/q/339421/-creating-base-activity-with-navigation-drawer-in-androidBeetle
R
3

As a little improvement to the solution pointed by @David-Crozier, in order to avoid the overlap of both animations (closing the NavigationDrawer and starting a new activity), you can include a little delay in your method as was done in the iosched app v2014:

private void onNavDrawerItemClicked(final int itemId) {
    if (itemId == getSelfNavDrawerItem()) {
        mDrawerLayout.closeDrawer(GravityCompat.START);
        return;
    }

    if (isSpecialItem(itemId)) {
        goToNavDrawerItem(itemId);
    } else {
        // launch the target Activity after a short delay, to allow the close animation to play
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                goToNavDrawerItem(itemId);
            }
        }, NAVDRAWER_LAUNCH_DELAY);

        // change the active item on the list so the user can see the item changed
        setSelectedNavDrawerItem(itemId);
        // fade out the main content
        View mainContent = findViewById(R.id.main_content);
        if (mainContent != null) {
            mainContent.animate().alpha(0).setDuration(MAIN_CONTENT_FADEOUT_DURATION);
        }
    }

    mDrawerLayout.closeDrawer(GravityCompat.START);
}

Here the link for reference: https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/BaseActivity.java

Rhynd answered 3/6, 2016 at 7:21 Comment(0)
N
1

The Fragment manager can be replaced as mentioned in the post:

https://guides.codepath.com/android/fragment-navigation-drawer#alternative-to-fragments

You can inflate a layout instead of using a fragment manager.

Narcoma answered 19/5, 2018 at 11:46 Comment(0)
T
0

In your mobile_navigation file XML. Add the following.

    <activity
    android:id="@+id/nav_custom"
    android:name="net.larntech.nav.CustomActivity"
    android:label="@string/menu_custom"
    tools:layout="@layout/activity_custom"
    />

navigation drawer

You can find the full tutorial using the link below. Android Studio Navigation Drawer

Ticon answered 12/6, 2021 at 18:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.