web-dev-qa-db-fra.com

Désactiver le tiroir de navigation, basculer le bouton d'accueil / l'indicateur vers le haut en fragments

La mise en place

J'ai une activité dont contentView est une instance d'un DrawerLayout, qui a un tiroir de navigation avec un indicateur de tiroir affiché dans la barre d'action. L'activité contient un Fragment, appelons-le ListFragment, qui contient une liste d'options. Lorsqu'une option est cliquée, je remplace le ListFragment par un DetailFragment.

Architecture of the application

À ce stade, je voudrais afficher une option de navigation "vers le haut" au lieu de l'indicateur du tiroir de navigation. Je peux afficher l'icône "haut" si je désactive l'indicateur de tiroir en appelant mDrawerToggle.setDrawerIndicatorEnabled(false), mais cela ne supprime que l'icône de tiroir - cela ne supprime pas la fonctionnalité - c'est-à-dire lorsque je clique le curseur, le tiroir de navigation est toujours ouvert.

De plus, dans ces sous-vues, je voudrais désactiver l'ouverture du tiroir en faisant glisser depuis le bord de l'écran. J'ai essayé de le faire en appelant setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) mais il ne semble pas avoir désactivé cette fonctionnalité.

J'ai essayé d'étendre la classe ActionBarDrawerToggle pour empêcher l'ouverture du tiroir lorsque l'indicateur est cliqué - cependant, tout ce qui se passe est que l'action prioritaire (la navigation "vers le haut") est effectuée, mais le tiroir s'ouvre toujours .

J'ai également implémenté les étapes dans Basculer entre Android Image du tiroir de navigation et Caret supérieur lors de l'utilisation de fragments . Cela fonctionne dans la mesure où l'affichage du curseur disparaît, mais malgré le remplacement de la valeur supérieure) la fonctionnalité du bouton, le menu s'ouvre toujours (l'application revient en arrière - elle ouvre également le tiroir).

Question

Donc, pour faire court: y a-t-il un moyen (de préférence propre et élégant, mais à ce stade, j'irai avec hacky) de réaliser ces choses lorsque ma racine de mise en page est un DrawerLayout:

  1. Remplacez l'indicateur de tiroir par un signe d'insertion "haut" (provisoirement réalisable via mDrawerToggle.setDrawerIndicatorEnabled(false))
  2. Empêcher le tiroir de s'ouvrir lorsque le curseur est cliqué, et remplacer à la place avec ma propre fonctionnalité "up"
  3. Empêchez le tiroir de s'ouvrir lorsque je fais glisser depuis le bord de l'écran.

Modifier

D'accord, il semble que si je remplace tous les deux ActionBarDrawerToggle ET onOptionsItemSelected, le menu ne s'ouvre pas lorsque je clique sur le curseur. Mais il s'ouvre toujours si je fais glisser depuis Edge. Aidez-moi!

46
Catherine

Ce n'est qu'une partie de la solution à laquelle je suis arrivé, mais il était assez difficile de comprendre ce bug, donc je laisse cela ici pour la postérité.

Voici comment je définissais le ListView pour mon tiroir de navigation:

<ListView
    Android:id="@+id/listview_drawer"
    Android:layout_width="240dp"
    Android:layout_height="match_parent"
    Android:layout_gravity="start|bottom"
    Android:background="#111"
    Android:choiceMode="singleChoice"
    Android:divider="@Android:color/transparent"
    Android:dividerHeight="0dp" />

Même après avoir appelé setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED), j'ai toujours pu ouvrir le tiroir.

Cependant, après avoir changé le layout_gravity En "start", Ce problème semble être résolu.

J'ai pu reproduire ce problème dans un exemple d'application de navigation uniquement, il semble donc qu'il s'agisse d'un problème reproductible qui n'est pas unique à ma situation.

22
Catherine

Petit code

public void setDrawerState(boolean isEnabled) {
    if ( isEnabled ) {
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        drawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_UNLOCKED);
        drawerToggle.setDrawerIndicatorEnabled(true);
        drawerToggle.syncState();

    }
    else {
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        drawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        drawerToggle.setDrawerIndicatorEnabled(false);
        drawerToggle.syncState();
    }
}
34
sonida

S'appuyant sur la réponse de Sonida. Après avoir appelé setDrawerIndicatorEnabled (false), onNavigateUp n'était pas encore appelé. Donc, je viens de créer un nouveau onClickListener qui l'appelait:

public void setDrawerState(boolean isEnabled) {
    if ( isEnabled ) {
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        drawerToggle.setDrawerIndicatorEnabled(true);
        drawerToggle.syncState();

    }
    else {
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        drawerToggle.setDrawerIndicatorEnabled(false);
        drawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onSupportNavigateUp();
            }
        });
        drawerToggle.syncState();
    }
}

je pense aussi

drawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_UNLOCKED);

a été déprécié, mais il fonctionne très bien sans lui.

11
luca992

Vous devez désactiver le balayage et désactiver le bouton d'accueil de la barre d'action:

Utilisez le code ci-dessous qui s'appuie sur le code déjà donné pour désactiver le balayage

  public void setDrawerState(boolean isEnabled) {
        if ( isEnabled ) {
            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
            mDrawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_UNLOCKED);
            mDrawerToggle.setDrawerIndicatorEnabled(true);
            mDrawerToggle.syncState();
            getActivity().getActionBar().setHomeButtonEnabled(true);

        }
        else {
            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            mDrawerToggle.onDrawerStateChanged(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            mDrawerToggle.setDrawerIndicatorEnabled(false);
            mDrawerToggle.syncState();
            getActivity().getActionBar().setHomeButtonEnabled(false);
        }
    }
2
jai

S'appuyant sur la réponse de @sonida Et après avoir utilisé les modifications apportées par @ luca992 et @jai.

J'ai essayé les codes suggérés ci-dessus, mais la flèche "vers le haut" ou "Retour" dans le côté gauche de la barre d'action n'apparaissait tout simplement pas dans mon application. Mais heureusement, j'ai pu résoudre ce problème.

J'ai dû ajouter cette ligne de code supplémentaire dans setNavigationDrawerState () [Ref: Android.support.v7.app.ActionBarDrawerToggle.setHomeAsUpIndicator ]

toggle.setHomeAsUpIndicator (R.drawable.ic_keyboard_backspace_white_24dp);

J'ai téléchargé le dessin: ic_keyboard_backspace_white_24dp de Material.io

Voici le code complet:

MainActivity.Java -> onCreate ()

DrawerLayout drawer;
ActionBarDrawerToggle toggle;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // Start: Code automatically generated by Android Studio
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

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

    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();
    // End: Code automatically generated by Android Studio

    // I had to add this listener as the "back" arrow was totally unresponsive
    // Thanks to @luca992
    toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onBackPressed();
        }
    });

    // Start: Code automatically generated by Android Studio
    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);
    // End: Code automatically generated by Android Studio

    // More custom code for other stuff
    // ...
}

MainActivity.Java -> setNavigationDrawerState ()

public void setNavigationDrawerState(boolean isEnabled) {
if ( isEnabled ) {
    drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
    toggle.setDrawerIndicatorEnabled(true);
    toggle.syncState();
}
else {
    drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
    toggle.setDrawerIndicatorEnabled(false);
    // the extra line of code goes here
    toggle.setHomeAsUpIndicator(R.drawable.ic_keyboard_backspace_white_24dp);    

    toggle.syncState();
}

MainActivity.Java -> onBackPressed ()

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else if(getSupportFragmentManager().getBackStackEntryCount() > 0){
        getSupportFragmentManager().popBackStack();
    }else {
        super.onBackPressed();
    }
}

MainActivity.Java -> startFragment () [fonction factice par exemple]

public void startFragment(){
    MyFrag myFrag = new MyFrag();

    getSupportFragmentManager()
        .beginTransaction()
        .replace(R.id.frag_container ,myFrag)
        .addToBackStack(null)
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
        .commit();
}

MyFrag.Java -> onViewCreated ()

@Override
public void onViewCreated (View view, Bundle savedInstanceState){
    super.onViewCreated(view, savedInstanceState);

    // Say, using an implemented interface Make call to MainActivitiy's  setNavigationDrawerState() passing false
    // setNavigationDrawerState(false)

    // ...
}

MyFrag.Java -> onDestroyView ()

@Override
public void onDestroyView(){
    // Say, using an implemented interface Make call to MainActivitiy's setNavigationDrawerState() passing true 
    // setNavigationDrawerState(true)

    super.onDestroyView();
}
1
Vinay Vissh