web-dev-qa-db-fra.com

Vue de navigation Androidx - `setNavigationItemSelectedListener` ne fonctionne pas

Qu'est-ce que je fais?

J'ai essayé de travailler avec Androidx Navigation Drawer (<com.google.Android.material.navigation.NavigationView>). J'ai lu la documentation ici , qui dit que pour gérer les sélections d'articles, nous pouvons utiliser setNavigationItemSelectedListener.

Remarque: J'utilise également le composant de navigation de JetPack.

Ci-dessous: main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.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:context=".MainActivity">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical">

        <androidx.appcompat.widget.Toolbar
            Android:id="@+id/toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            Android:background="@color/colorPrimary"
            Android:theme="@style/ThemeOverlay.AppCompat.Dark" />

        <fragment
            Android:id="@+id/nav_Host_fragment"
            Android:name="androidx.navigation.fragment.NavHostFragment"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" />

    </LinearLayout>

    <com.google.Android.material.navigation.NavigationView
        Android:id="@+id/navigationView"
        Android:layout_width="wrap_content"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        Android:fitsSystemWindows="true"
        app:menu="@menu/drawer_menu" />

</androidx.drawerlayout.widget.DrawerLayout>

Voici: MainActivity.Java

import Android.os.Bundle;
import Android.view.MenuItem;
import Android.widget.Toast;

import com.google.Android.material.navigation.NavigationView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;

public class MainActivity extends AppCompatActivity {

    public Toolbar toolbar;

    public DrawerLayout drawerLayout;

    public NavController navController;

    public NavigationView navigationView;

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

        setupNavigation();

    }

    // Setting Up One Time Navigation
    private void setupNavigation() {

        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        drawerLayout = findViewById(R.id.drawer_layout);

        navigationView = findViewById(R.id.navigationView);
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();
                return false;
            }
        });

        navController = Navigation.findNavController(this, R.id.nav_Host_fragment);

        NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout);

        NavigationUI.setupWithNavController(navigationView, navController);

    }

    @Override
    public boolean onSupportNavigateUp() {
        return NavigationUI.navigateUp(drawerLayout, Navigation.findNavController(this, R.id.nav_Host_fragment));
    }

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

}

Situation:

Tout s'affiche correctement, j'obtiens le Drawer au moment de l'exécution, j'obtiens également le Hamburger, cela fonctionne très bien pour afficher le NavigationView avec les éléments de menu.

Ci-dessous: tiroir_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">

    <group Android:checkableBehavior="single">

        <item
            Android:id="@+id/first"
            Android:icon="@mipmap/ic_launcher"
            Android:title="First" />

        <item
            Android:id="@+id/second"
            Android:icon="@mipmap/ic_launcher"
            Android:title="Second" />

        <item
            Android:id="@+id/third"
            Android:icon="@mipmap/ic_launcher"
            Android:title="Third" />

    </group>

</menu>

Problème:

En tapant sur les éléments du menu, il ne répond pas à mes événements de clic, alias onNavigationItemSelected. Comme vous pouvez voir mon MainActivity.Java, le Toast n'apparaît pas et aucun des ID de menu ne fonctionne à l'intérieur du commutateur.

J'ai essayé de nombreux exemples et différentes façons d'y parvenir.

Existe-t-il un moyen de faire en sorte que les éléments du menu répondent à mes événements sélectionnés?

Si vous avez besoin de plus de détails à ce sujet, veuillez commenter ci-dessous.

Merci beaucoup pour l'aide.

9
Unt

Je l'ai compris les gars.

Au cas où quelqu'un en aurait besoin, je le poste ici.

Au lieu de cela:

navigationView = findViewById(R.id.navigationView);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();
        return false;
    }
});

navController = Navigation.findNavController(this, R.id.nav_Host_fragment);

NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout);

NavigationUI.setupWithNavController(navigationView, navController);

J'ai changé pour:

navigationView = findViewById(R.id.navigationView);

navController = Navigation.findNavController(this, R.id.nav_Host_fragment);

NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout);

NavigationUI.setupWithNavController(navigationView, navController);

navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();
        return false;
    }
});

Et cela a fonctionné, peut-être que nous devons tout configurer avant d'attacher le onNavigationSelector.

7
Unt

Vous n'avez peut-être pas compris tous les effets secondaires du changement de commande.

NavigationUI.setupWithNavController(navigationView, navController); // Line 1
navigationView.setNavigationItemSelectedListener({...}) // Line 2

NavigationUI attache en interne NavigationView.OnNavigationItemSelectedListener au NavigationView à Line1. Vous remplacez cet écouteur par votre écouteur personnalisé dans Line 2.

Cela signifie que navController ne fonctionnera pas et vous devez gérer toutes les actions de navigation manuellement dans votre écouteur personnalisé. Ainsi, la solution complète pourrait être quelque chose comme:

NavigationUI.setupWithNavController(navigationView, navController);

navigationView.setNavigationItemSelectedListener(
        new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {

        // TODO: do stuff
        Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();

        // You need this line to handle the navigation
        boolean handled = NavigationUI.onNavDestinationSelected(menuItem, navController);
        if (handled) {
            ViewParent parent = navigationView.getParent();
            if (parent instanceof DrawerLayout) {
                ((DrawerLayout) parent).closeDrawer(navigationView);
            }
        }

        return handled;
    }
});

Remarque: vous souhaiterez peut-être toujours appeler setupWithNavController avant de joindre votre écouteur personnalisé, car il fait autre chose que d'attacher l'écouteur de clic d'élément de navigation.

5
Sanlok Lee

Dans le cas où quelqu'un qui cherche encore répondra comment avoir les deux: NavigationController pour gérer les éléments NavigationView, mais aussi pour avoir une action spécifique à l'intérieur de NavigationView.

Dans les éléments du menu de configuration du fichier menu.xml, comme d'habitude:

   <menu>
        <item
                Android:id="@+id/fragment_settings"
                Android:icon="@drawable/ic_settings"
                Android:orderInCategory="3"
                Android:title="@string/settings" />

        <item
                Android:id="@+id/share_app"
                Android:icon="@drawable/ic_share"
                Android:orderInCategory="4"
                Android:onClick="shareApp"
                Android:title="@string/share_to_friends" />

        <item
                Android:id="@+id/fragment_about"
                Android:icon="@drawable/ic_info"
                Android:orderInCategory="5"
                Android:title="@string/about" />
    </menu>

Définissez d'abord une méthode onClick"shareApp" pour l'élément de menu "share_app". Ensuite, dans votre activité, créez une méthode comme celle-ci:

fun shareApp(item:MenuItem) {
    logD("share app clicked!")
    val intent = Intent(Intent.ACTION_SEND).apply {
        putExtra(Intent.EXTRA_TEXT, "some text to send...")
        type = "text/*"
    }
    startActivity(Intent.createChooser(intent, "Share app..."))
}

N'oubliez pas d'attacher une barre d'outils, NavigationView et DrawerLayout à NavController dans la méthode d'activité amusante onCreate (savedInstanceState: Bundle?) (Ou où vous voulez)

override fun onCreate(savedInstanceState: Bundle?) {
    setTheme(R.style.AppTheme)
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    setupActionBarWithNavController(navController, drawer_layout)
    setupWithNavController(nav_view, navController)
    setupWithNavController(toolbar, navController, drawer_layout)

}
3