自定义Toolbar下Navigation Drawer选中监听异常求助
问题描述
- 打开Navigation Drawer无报错,但选中菜单项时抽屉会自动关闭
- 选中菜单项时
NavigationItemSelectedListener中设置的Toast消息未显示 - 使用自定义Toolbar(以ImageView作为侧边菜单按钮),默认Toolbar下功能正常
相关布局代码
<?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:layout_width="match_parent" android:layout_height="match_parent" tools:context=".CustomToolbar" android:id="@+id/drawer_layout"> <com.google.android.material.navigation.NavigationView android:id="@+id/navigation_view" android:layout_width="wrap_content" android:layout_height="match_parent" app:headerLayout="@layout/header_file" app:menu="@menu/main_manu" android:layout_gravity="start"/> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bggradient"> <include android:id="@+id/toolbar" layout="@layout/layout_toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> </ScrollView> </androidx.drawerlayout.widget.DrawerLayout>
相关Activity代码
public class CustomToolbar extends AppCompatActivity { private Toolbar toolbar; private DrawerLayout drawer; private NavigationView navigationView; private ActionBarDrawerToggle toggle; private ImageView side_menu; @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (toggle.onOptionsItemSelected(item)){ return true; } return super.onOptionsItemSelected(item); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_toolbar); toolbar = (Toolbar) findViewById(R.id.navigation_bar); side_menu = findViewById(R.id.side_menu); drawer = findViewById(R.id.drawer_layout); navigationView = findViewById(R.id.navigation_view); setSupportActionBar(toolbar); toggle = new ActionBarDrawerToggle(this, drawer, R.string.open, R.string.close); drawer.addDrawerListener(toggle); toggle.syncState(); side_menu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { drawer.openDrawer(Gravity.LEFT); } }); navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.home_menu: { Toast.makeText(CustomToolbar.this, "Home Selected", Toast.LENGTH_SHORT).show(); } case R.id.community_menu: { Toast.makeText(CustomToolbar.this, "Community Selected", Toast.LENGTH_SHORT).show(); } case R.id.posts_menu: { Toast.makeText(CustomToolbar.this, "Posts Selected", Toast.LENGTH_SHORT).show(); } case R.id.website_menu: { Toast.makeText(CustomToolbar.this, "Website Selected", Toast.LENGTH_SHORT).show(); } case R.id.share_menu: { Toast.makeText(CustomToolbar.this, "Share Selected", Toast.LENGTH_SHORT).show(); } case R.id.feedback_menu: { Toast.makeText(CustomToolbar.this, "Feedback Selected", Toast.LENGTH_SHORT).show(); } case R.id.about_menu: { Toast.makeText(CustomToolbar.this, "About us Selected", Toast.LENGTH_SHORT).show(); } case R.id.logout_menu: { Toast.makeText(CustomToolbar.this, "Logout Selected", Toast.LENGTH_SHORT).show(); } } return false; } }); } @Override public void onBackPressed() { if (drawer.isDrawerOpen(GravityCompat.START)){ drawer.closeDrawer(GravityCompat.START); } else { super.onBackPressed(); } } }
解决方案
1. 修正DrawerLayout子布局顺序
DrawerLayout要求主内容布局必须是第一个子View,抽屉布局(NavigationView)需放在主内容布局之后。原布局中NavigationView的位置错误,会导致触摸事件处理异常,调整后代码如下:
<androidx.drawerlayout.widget.DrawerLayout ...> <!-- 主内容布局放在第一个位置 --> <ScrollView ...> ... </ScrollView> <!-- 抽屉布局移到主内容布局之后 --> <com.google.android.material.navigation.NavigationView .../> </androidx.drawerlayout.widget.DrawerLayout>
2. 修复Toolbar的ID引用错误
Activity中toolbar = (Toolbar) findViewById(R.id.navigation_bar)的ID与布局中include的Toolbar ID@+id/toolbar不匹配,修正为:
toolbar = findViewById(R.id.toolbar);
3. 给Switch Case添加break语句
原代码中每个case都未添加break,会导致所有case的Toast逻辑依次执行,最后触发默认的抽屉关闭行为。给每个case添加break:
switch (item.getItemId()) { case R.id.home_menu: { Toast.makeText(CustomToolbar.this, "Home Selected", Toast.LENGTH_SHORT).show(); break; } case R.id.community_menu: { Toast.makeText(CustomToolbar.this, "Community Selected", Toast.LENGTH_SHORT).show(); break; } // 其余case同理添加break ... }
4. 修改NavigationItemSelectedListener的返回值并手动关闭抽屉
返回false会让系统认为未处理该事件,自动关闭抽屉。改为返回true表示已处理事件,同时手动关闭抽屉:
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { // 处理各个菜单项逻辑 ... } // 手动关闭抽屉 drawer.closeDrawer(GravityCompat.START); return true; } });
5. 移除冗余的ActionBarDrawerToggle代码(可选)
因使用自定义ImageView打开抽屉,ActionBarDrawerToggle是配合默认Toolbar汉堡按钮使用的,若不需要默认汉堡按钮,可移除相关代码避免冲突:
// 移除以下代码 // toggle = new ActionBarDrawerToggle(this, drawer, R.string.open, R.string.close); // drawer.addDrawerListener(toggle); // toggle.syncState(); // 同时修改onOptionsItemSelected方法 @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { return super.onOptionsItemSelected(item); }
内容的提问来源于stack exchange,提问作者Roshan Poojary
相关产品推荐
相关产品推荐

