Java Androidx 导航视图 - `setNavigationItemSelectedListener` 不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/53131591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:43:23  来源:igfitidea点击:

Androidx Navigation View - `setNavigationItemSelectedListener` Doesn't Work

javaandroidnavigation-drawerandroid-architecture-navigation

提问by Unt

What am I doing?

我在做什么?

I have been trying to work with Androidx Navigation Drawer(<com.google.android.material.navigation.NavigationView>). I've read the documentation Here, which says that for handling item selections we can use setNavigationItemSelectedListener.

我一直在尝试使用 Androidx Navigation Drawer( <com.google.android.material.navigation.NavigationView>)。我已经阅读了此处的文档,其中说明我们可以使用setNavigationItemSelectedListener.

Note:I am using JetPack's Navigation Component as well.

注意:我也在使用 JetPack 的导航组件。

Below is: main_activity.xml

下面是: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>

Here is: MainActivity.java

这是: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:

情况:

Everything displays fine, I get the Drawerat runtime, I also get the Hamburger, It works fine to display the NavigationViewwith the menu items.

一切都显示得很好,我Drawer在运行时得到了,我也得到了Hamburger,它可以很好地NavigationView与菜单项一起显示。

Below is: drawer_menu.xml

下面是:drawer_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>

Problem:

问题:

On tapping the menu items, it does not respond to my click events, a.k.a onNavigationItemSelected. As you can see my MainActivity.java, the Toastdoes not appear neither any of the menu ids work inside switch.

在点击菜单项时,它不会响应我的点击事件,也就是onNavigationItemSelected。如您所见MainActivity.javaToast在 switch 中没有出现任何菜单 ID。

I've been trying many examples and different ways to get this done.

我一直在尝试许多示例和不同的方法来完成这项工作。

Is there any way to make menu items respond to my select events?

有没有办法让菜单项响应我的选择事件?

If you need any more details on this, please do comment below.

如果您需要更多详细信息,请在下面发表评论。

Thank You so much for the Help.

十分感谢你的帮助。

回答by Unt

I Figured it out guys.

我想通了伙计们。

Just in case if someone needs it, I'm posting it here.

以防万一有人需要它,我把它张贴在这里。

Instead of this:

取而代之的是:

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

I changed to:

我改为:

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

And it worked, may be we need to configure everything before attaching the onNavigationSelector.

它有效,可能是我们需要在附加onNavigationSelector.

回答by Sanlok Lee

You might not have understood the full side effect of switching the order.

您可能不了解切换顺序的全部副作用。

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

The NavigationUIinternally attaches NavigationView.OnNavigationItemSelectedListenerto the NavigationViewat Line1. You are overriding that listener with your custom listener in Line 2.

NavigationUI内部附加NavigationView.OnNavigationItemSelectedListenerNavigationViewLine1。您正在使用自定义侦听器覆盖该侦听器Line 2

This means navControllerwon't work and you have to handle all of the navigation actions manually in your custom listener. So the full solution might be something along the lines of:

这意味着navController不起作用,您必须在自定义侦听器中手动处理所有导航操作。所以完整的解决方案可能是这样的:

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

Note: You still might want to call setupWithNavControllerbefore attaching your custom listener because it does things other than attaching navigation item click listener.

注意:您可能仍然希望setupWithNavController在附加自定义侦听器之前调用,因为它除了附加导航项单击侦听器之外还执行其他操作。

回答by ?emsudin Tafilovi?

In case that someone still looking for answer how to have both: NavigationController to handle NavigationView items, but also to have some specific action inside of the NavigationView.

如果有人仍在寻找如何同时拥有的答案: NavigationController 来处理 NavigationView 项目,但还要在 NavigationView 内部进行一些特定的操作。

In menu.xml file setup menu items as usual:

在 menu.xml 文件中设置菜单项照常:

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

First define a onClickmethod "shareApp"for the "share_app"menu item. Then in your activity create method like this:

首先为“share_app”菜单项定义一个onClick方法“shareApp”。然后在您的活动中创建这样的方法:

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..."))
}

Don't forget to attach a Toolbar, NavigationView and DrawerLayout to NavController in the override fun onCreate(savedInstanceState: Bundle?) method of activity (or where ever you want)

不要忘记在覆盖 fun onCreate(savedInstanceState: Bundle?) 活动方法(或您想要的任何地方)中将 Toolbar、NavigationView 和 DrawerLayout 附加到 NavController

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)

}