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
Androidx Navigation View - `setNavigationItemSelectedListener` Doesn't Work
提问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 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, a.k.a onNavigationItemSelected
. As you can see my MainActivity.java
, the Toast
does not appear neither any of the menu ids work inside switch.
在点击菜单项时,它不会响应我的点击事件,也就是onNavigationItemSelected
。如您所见MainActivity.java
,Toast
在 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 NavigationUI
internally attaches NavigationView.OnNavigationItemSelectedListener
to the NavigationView
at Line1
. You are overriding that listener with your custom listener in Line 2
.
该NavigationUI
内部附加NavigationView.OnNavigationItemSelectedListener
到NavigationView
的Line1
。您正在使用自定义侦听器覆盖该侦听器Line 2
。
This means navController
won'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 setupWithNavController
before 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)
}