简体   繁体   English

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

[英]Androidx Navigation View - `setNavigationItemSelectedListener` Doesn't Work

What am I doing?我在做什么?

I have been trying to work with Androidx Navigation Drawer( <com.google.android.material.navigation.NavigationView> ).我一直在尝试使用 Androidx Navigation Drawer( <com.google.android.material.navigation.NavigationView> )。 I've read the documentationHere , which says that for handling item selections we can use setNavigationItemSelectedListener .我已经阅读了文档Here ,它说为了处理项目选择,我们可以使用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 Drawer at runtime, I also get the Hamburger , It works fine to display the NavigationView with 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, aka onNavigationItemSelected .在点击菜单项时,它不会响应我的点击事件,也就是onNavigationItemSelected As you can see my MainActivity.java , the Toast does not appear neither any of the menu ids work inside switch.如您所见,我的MainActivity.java没有出现Toast也没有任何菜单 ID 在 switch 内工作。

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.十分感谢你的帮助。

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之前配置所有内容。

You might not have understood the full side effect of switching the order.您可能不了解切换顺序的全部副作用。

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

The NavigationUI internally attaches NavigationView.OnNavigationItemSelectedListener to the NavigationView at Line1 . NavigationUI内部将NavigationView.OnNavigationItemSelectedListener附加到Line1处的NavigationView You are overriding that listener with your custom listener in Line 2 .您正在Line 2使用自定义侦听器覆盖该侦听器。

This means navController won't work and you have to handle all of the navigation actions manually in your custom listener.这意味着navController将无法工作,您必须在自定义侦听器中手动处理所有导航操作。 So the full solution might be something along the lines of:所以完整的解决方案可能是这样的:

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 setupWithNavController before attaching your custom listener because it does things other than attaching navigation item click listener.注意:您可能仍然希望在附加自定义侦听setupWithNavController之前调用setupWithNavController ,因为它除了附加导航项单击侦听器之外还执行其他操作。

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 onClick method "shareApp" for the "share_app" menu item.首先为“share_app”菜单项定义一个onClick方法“shareApp” Then in your activity create method like this:然后在您的活动中创建这样的方法:

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)

}

Try this, this one is perfect solution I hope.试试这个,这是我希望的完美解决方案。 Simply write below code to navigate to your fragments.只需编写以下代码即可导航到您的片段。

@Override
protected void onCreate(Bundle savedInstanceState) {
    ..........
    ..........
    navigationView.setNavigationItemSelectedListener(this);    
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {

    menuItem.setChecked(true);

    drawerLayout.closeDrawers();

    int id = menuItem.getItemId();

    switch (id) {

        case R.id.first:
            navController.navigate(R.id.firstFragment);// **firstFragment** is the id that is written the file under **res/navigation/mobile_navigation.xml** 
            break;

        case R.id.second:
            navController.navigate(R.id.secondFragment);
            break;

        case R.id.third:
            navController.navigate(R.id.thirdFragment);
            break;

    }
    return true;

}

MainActivity should implement OnNavigationItemSelectedListener, your code should look like MainActivity 应该实现 OnNavigationItemSelectedListener,你的代码应该看起来像

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
...
}

The correct order正确的顺序

navView.setupWithNavController(navController)
navView.setNavigationItemSelectedListener {
    Log.e(TAG, "onCreate: ", )
        true
}

If you don't execute navView.setupWithNavController first, NavView.setNavigationItemSelectedListener will not take effect.如果不先执行navView.setupWithNavControllerNavView.setNavigationItemSelectedListener不会生效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM