【问题标题】:How to fix Android studio 3.5 navigation activity template onNavigationItemSelected not working如何修复 Android Studio 3.5 导航活动模板 onNavigationItemSelected 不起作用
【发布时间】:2019-08-29 03:34:40
【问题描述】:

我从 Android Studio 3.5 模板创建了一个新的抽屉式导航活动,但即使我正在监听 NavigationItemSelected,菜单项也无法点击。

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

    private AppBarConfiguration mAppBarConfiguration;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        mAppBarConfiguration = new AppBarConfiguration.Builder(
                R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow,
                R.id.nav_tools, R.id.nav_share, R.id.nav_send)
                .setDrawerLayout(drawer)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
        NavigationUI.setupWithNavController(navigationView, navController);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
        return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                || super.onSupportNavigateUp();
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        Toast.makeText(this, menuItem.getTitle(), Toast.LENGTH_SHORT).show();
        return true;
    }
}

当我从抽屉中单击一个项目时,抽屉只是关闭而不是显示 onNavigationItemSelected 方法中定义的 Toast。

【问题讨论】:

  • edit您的问题提供具有<DrawerLayout>的布局XML。
  • 这在 Android Studio 4.0.1 稳定版中仍然是一个问题......(你在听吗,谷歌?)......问题的公认答案解决了这个问题。
  • 如果有人使用 4.1(目前不稳定的版本)或 4.2 测试版可以发表评论,如果它已在这些版本中得到修复,那会很好吗?
  • 所以 - 在刚刚发布的 Android Studio 4.1 稳定版中仍然存在问题.....应该由 Google 修复。这里仍然需要接受的解决方案。
  • 所以最后似乎在Android Studio 4.1.2中修复了,xml文件中的顺序是正确的。

标签: android


【解决方案1】:

这个问题是由主要内容的xml文件排序问题引起的

默认顺序:

<com.google.android.material.navigation.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer" />

<include
    layout="@layout/app_bar_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

更改为以下顺序:

<include
    layout="@layout/app_bar_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<com.google.android.material.navigation.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer" />

【讨论】:

  • 对于那些想知道为什么这是正确答案的人,它与 Z 顺序有关,NavigationView 必须位于其他控件之上才能接收输入。 XML 布局文件中的控件按底部 -> 顶部的顺序排列,因此要成为最顶部的控件,必须在最后声明。
  • @BitByteDog 非常感谢您对 XML 布局的 Z 顺序的解释。我也很困惑为什么改变顺序会产生这样的效果。
  • DrawerLayout 的 Android 文档是具体的,内容视图必须放在第一位,NavigationView 放在第二位。排序很重要。还有其他几个容器视图对排序很重要,例如FrameLayout。只需检查每个控件的文档,看看视图的顺序是否重要。
  • 干得好,谷歌。
【解决方案2】:

在 XML 中,活动中的标签 &lt;androidx.drawerlayout.widget.DrawerLayout&gt; 先重排和&lt;com.google.android.material.navigation.NavigationView&gt; 第二 。 内部 java onCreate 示例:

navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(@NonNull NavController controller,
                                             @NonNull NavDestination destination, @Nullable Bundle arguments) {
                if(destination.getId() == R.id.nav_home) {
                    Toast.makeText(Permissions_Display.this,"home",Toast.LENGTH_LONG).show();
                } if(destination.getId() == R.id.nav_gallery) {
                    Toast.makeText(Permissions_Display.this,"nav_gallery",Toast.LENGTH_LONG).show();
                }
                if(destination.getId() == R.id.nav_slideshow) {
                    Toast.makeText(Permissions_Display.this,"nav_slideshow",Toast.LENGTH_LONG).show();
                } if(destination.getId() == R.id.nav_tools) {
                    Toast.makeText(Permissions_Display.this,"nav_tools",Toast.LENGTH_LONG).show();
                }
                if(destination.getId() == R.id.nav_share) {
                    Toast.makeText(Permissions_Display.this,"nav_share",Toast.LENGTH_LONG).show();
                } if(destination.getId() == R.id.nav_send) {
                    Toast.makeText(Permissions_Display.this,"nav_send",Toast.LENGTH_LONG).show();
                }
            }
        });

【讨论】:

    【解决方案3】:

    **

    对于可点击的菜单项

    ** NavController 提供了一个 OnDestinationChangedListener 接口,当 NavController 的当前目标或其参数更改时调用该接口。可以通过 addOnDestinationChangedListener() 方法注册新的侦听器。请注意,调用 addOnDestinationChangedListener() 时,如果当前目的地存在,则立即将其发送给您的侦听器。

    /////////////////////////////////////// //////////////////////

    navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
       @Override
       public void onDestinationChanged(@NonNull NavController controller,
               @NonNull NavDestination destination, @Nullable Bundle arguments) {
           if(destination.getId() == R.id.gallery) {
               //statements
           } else {
           //statements
    }
       }
    });
    

    【讨论】:

      【解决方案4】:

      当您调用NavigationUI.setupWithNavController(navigationView, navController) 时,您是说您希望NavController 处理来自您的NavigationView 的点击事件,并按照the NavigationUI documentation 导航到相关屏幕。这必然会在内部调用setNavigationItemSelectedListener(),覆盖您之前在onCreate() 中调用的setNavigationItemSelectedListener()。如果您已将您的 NavigationView 连接到应用程序中的片段(就像模板开箱即用一样),则无需自己调用 setNavigationItemSelectedListener

      当然,您应该确保您的布局没有改变导航抽屉活动默认为您提供的内容 - 有一个 known issue with Android Studio 3.5 可能导致视图顺序发生更改,这会破坏像 DrawerLayout 这样的情况(孩子的顺序很重要)

      【讨论】:

      • 所以,它应该仍然调用onNavigationItemSelected(),对吧?我假设他们已经添加了setNavigationItemSelectedListener() 调用以进行调试。
      • @MikeM。 - NavigationView 一次只允许设置一个侦听器 - 由于 NavigationUI 是最后设置的,因此会调用其内部侦听器。
      • 哎呀,没关系。我把它和别的东西混淆了(那不存在;我还不熟悉导航)。我的错。无论如何,我仍然敢打赌,在它无法开箱即用后,这是一次调试尝试。
      • @MatteoBelfiori 如果您的问题与我看到的相同,this issue in the 3.5 upgrade 会导致 XML 重新排序不正确,并且它会将 &lt;NavigationView&gt; 移动到主要的上方(因此也位于后面) &lt;DrawerLayout&gt; 中的内容。您需要将&lt;NavigationView&gt; 移动到&lt;include&gt; 之后(或者您可能对主要内容的其他任何内容)。然后按照该链接帖子上接受的答案中的步骤进行操作,以便以后重新格式化/重构时不会再次发生。
      • @MikeM.Oh 伙计,非常感谢。现在它可以工作了,只需按照您所说的移动 NavigationView 即可。非常感谢!!
      【解决方案5】:
      navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
          @Override
          public void onDestinationChanged(@NonNull NavController controller,
                                           @NonNull NavDestination destination, @Nullable Bundle arguments) {
              if(destination.getId() == R.id.nav_cart) {
                  Toast.makeText(HomeActivity.this,"nav_cart",Toast.LENGTH_LONG).show();
              } if(destination.getId() == R.id.nav_orders) {
                  Intent in =new Intent(HomeActivity.this, OrdersActivity.class);
                  startActivity(in);
                  Toast.makeText(HomeActivity.this,"nav_gallery",Toast.LENGTH_LONG).show();
              }
              if(destination.getId() == R.id.nav_categories) {
                  Toast.makeText(HomeActivity.this,"nav_categories",Toast.LENGTH_LONG).show();
              }
              if(destination.getId() == R.id.nav_settings) {
                  Intent in =new Intent(HomeActivity.this, SettingsActivity.class);
                  startActivity(in);
                  Toast.makeText(HomeActivity.this,"nav_settings",Toast.LENGTH_LONG).show();
              } if(destination.getId() == R.id.nav_logout) {
                  Toast.makeText(HomeActivity.this,"nav_logout",Toast.LENGTH_LONG).show();
              }
          }
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-08-04
        • 1970-01-01
        • 1970-01-01
        • 2020-01-15
        • 2016-03-10
        • 2015-12-25
        • 2019-07-01
        相关资源
        最近更新 更多