210 votes

Le même tiroir de navigation dans différentes activités

J'ai créé un tiroir de navigation fonctionnel comme celui qui est présenté dans le tutoriel sur le site de l développeur.Android.com site web. Mais maintenant, je veux utiliser un tiroir de navigation, que j'ai créé dans la classe NavigationDrawer.class pour plusieurs activités dans mon application.

Je me demande si quelqu'un ici peut faire un petit tutoriel qui explique comment utiliser un tiroir de navigation pour plusieurs activités.

Je l'ai lu en premier sur ce site. Tiroir de navigation Android sur plusieurs activités

mais cela n'a pas fonctionné sur mon projet

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);
}
}

Dans cette activité, je veux avoir le tiroir de navigation, j'ai donc étendu 'NavigationDrawer' et dans d'autres activités, je veux utiliser le même tiroir de navigation.

  public class SampleActivity extends NavigationDrawer {...}

1 votes

Vous pouvez trouver les exemples aquí .

1 votes

Vous pouvez trouver de : stackoverflow.com/questions/33009469/

189voto

Kevin van Mierlo Points 1382

Si vous voulez un tiroir de navigation, vous devez utiliser des fragments. J'ai suivi ce tutoriel la semaine dernière et cela fonctionne très bien :

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

Vous pouvez également télécharger un exemple de code à partir de ce tutoriel, pour voir comment vous pouvez procéder.


Sans fragments :

Il s'agit du code de votre BaseActivity :

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);
    }
}

Toutes les autres activités qui doivent avoir un tiroir de navigation doivent étendre cette activité au lieu de l'activité elle-même, par exemple :

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 :

J'ai moi-même rencontré quelques difficultés, voici donc une solution si vous obtenez des NullPointerExceptions. Dans BaseActivity, changez la fonction onCreate en protected void onCreateDrawer() . Le reste peut rester inchangé. Dans les activités qui étendent BaseActivity, mettez le code dans cet ordre :

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

Ceci m'a aidé à résoudre mon problème, j'espère que cela vous aidera !

Voilà comment vous pouvez créer un tiroir de navigation avec plusieurs activités. Si vous avez des questions, n'hésitez pas à les poser.


Edit 2 :

Comme l'a dit @GregDan votre BaseActivity peut également remplacer setContentView() et appeler onCreateDrawer à cet endroit :

@Override 
public void setContentView(@LayoutRes int layoutResID) 
{ 
    super.setContentView(layoutResID); 
    onCreateDrawer() ;
}

0 votes

J'ai créé un tiroir de navigation fonctionnel, mais je souhaite maintenant utiliser un tiroir de navigation dans plusieurs activités.

0 votes

La solution consiste à utiliser des fragments au lieu d'activités. Je ne vois pas pourquoi vous voudriez utiliser des activités plutôt que des fragments.

8 votes

Je ne veux pas utiliser des activités sur des fragments, je veux juste utiliser des activités différentes qui utilisent toutes le même tiroir de navigation. Je veux l'activité, parce que là je peux utiliser différents types de mise en page comme la vue glissante, la vue de la carte...

35voto

WindRider Points 1363

J'ai trouvé la meilleure mise en œuvre. Elle se trouve dans le Google I/O 2014 app.

Ils utilisent la même approche que celle de Kevin. Si vous pouvez vous abstraire de tout ce qui n'est pas nécessaire dans l'application d'E/S, vous pouvez extraire tout ce dont vous avez besoin et il est assuré par Google que c'est une utilisation correcte du modèle de tiroir de navigation. Chaque activité a éventuellement un DrawerLayout comme disposition principale. La partie intéressante est la façon dont la navigation vers d'autres écrans est effectuée. Elle est implémentée dans BaseActivity comme ça :

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

Cela diffère de la manière courante de remplacer le fragment actuel par une transaction de fragment. Mais l'utilisateur ne perçoit pas de différence visuelle.

0 votes

Cette année, je n'arrive pas à comprendre comment ils commencent de nouvelles activités et cela fonctionne parfaitement. C'est une grande application à travailler.

0 votes

@hitch.united C'est parce qu'ils utilisent beaucoup de fragments et seulement quelques activités.

0 votes

@hitch.united, ils remplacent probablement l'animation de l'activité avec overridePendingTransitions .

8voto

jwehrle Points 514

Cette réponse a donc quelques années de retard, mais quelqu'un pourrait l'apprécier. Android nous a donné un nouveau widget qui facilite l'utilisation d'un tiroir de navigation avec plusieurs activités.

Android.support.design.widget.NavigationView est modulaire et possède sa propre disposition dans le dossier du menu. La façon dont vous l'utilisez est d'envelopper les mises en page xml de la manière suivante :

  1. Le Root Layout est un Android.support.v4.widget.DrawerLayout qui contient deux enfants : un <include ... /> pour la disposition qui est enveloppée (voir 2) et un fichier 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 est simplement un LinearLayout avec orientation = vertical pour l'en-tête de votre Drawar de navigation.

activity_main_drawer est un menu xml dans votre répertoire res/menu. Il peut contenir des éléments et des groupes de votre choix. Si vous utilisez la galerie AndroidStudio, l'assistant en créera un de base pour vous et vous pourrez voir quelles sont vos options.

  1. La mise en page de la barre d'applications est généralement constituée d'un Android.support.design.widget.CoordinatorLayout, qui comprend deux enfants : un Android.support.design.widget.AppBarLayout (qui contient une barre d'outils Android.support.v7.widget.Toolbar) et un <include ... > pour votre contenu réel (voir 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. La mise en page du contenu peut être celle que vous souhaitez. Il s'agit de la mise en page qui contient le contenu principal de l'activité (sans le tiroir de navigation ou la barre d'application).

Ce qui est intéressant dans tout cela, c'est que vous pouvez envelopper chaque activité dans ces deux mises en page, mais que votre NavigationView (voir étape 1) pointe toujours vers activity_main_drawer (ou autre). Cela signifie que vous aurez le même(*) tiroir de navigation sur toutes les activités.

  • Ils ne seront pas les mêmes instance de NavigationView mais, pour être honnête, cela n'était pas possible même avec la solution BaseActivity décrite ci-dessus.

8voto

Levon Petrosyan Points 1012

Le moyen le plus simple de réutiliser un tiroir de navigation commun à un groupe d'activités

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

6voto

MicroR Points 133

Pour tous ceux qui cherchent à faire ce que l'affiche originale demande, veuillez envisager d'utiliser des fragments à la place, comme Kevin l'a dit. Voici un excellent tutoriel sur la façon de le faire :

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

Si vous choisissez d'utiliser des activités au lieu de fragments, vous allez vous heurter au problème du tiroir de navigation qui est recréé chaque fois que vous naviguez vers une nouvelle activité. Cela se traduit par un rendu laid et lent du tiroir de navigation à chaque fois.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X