目录
NaviagtionView(导航视图)需与DrawerLayout(绘制布局)配合使用。
DrawerLayout中的Navigation有两种表现方式,左划出和右划出,可在<NaviagtionView>标签中使用android:layout_gravity属性设置,值为start时为左划出,为end时为右划出。一个DrawerLayout中可以同时含有左划出和右划出的两个导航视图,和Activity主体空间。
NaviagtionView中有两部分,上部分的header和下部分的menu,可在<NaviagtionView>标签中使用android:headerLayout和android:menu属性设置。但这两个部分也可以有不设置的,或都不设置。其中菜单可以为自定义菜单项的菜单。
1. 基础使用方法:
(1) 准备NavigationView的hearderLayout和menu的XML文件
NavigationView默认展示菜单的title和icon的黑色阴影图标,但NavigationView支持显示自定义菜单项布局的菜单,详情请见下文。
<menu>中tools:showIn="navigation_view"可让预览图为菜单在导航视图中的样子。
// res\layout\navigation_view_header_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- 该部分为NaviagtionView上部分,高度不能为match_parent,要为menu留空间 !-->
</RelativeLayout>
// res\menu\navigation_view_menu.xml
<!-- 该菜单用于NavigationView下部分 !-->
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:showIn="navigation_view">
<item
android:id="@+id/item1"
android:title="title1"
android:icon="@drawable/icon1" />
<item
android:id="@+id/item2"
android:title="title2"
android:icon="@drawable/icon2" />
</menu>
(2) 创建DrawerLayout,并在DrawerLayout放置NavigationView
请确保NavigationView位于DrawerLayout中所有控件的最后,确保它是 DrawerLayout 的最后一个子 View。这样可以确保 NavigationView 处于较高的 Z 轴顺序,使其能够响应触摸事件。
在DrawerLayout中使用tools:openDrawer属性可以使预览图中的NavigationView展开,方便编写。
在DrawerLayout中放入NavigationView后一定要设置android:layout_gravity为start或end,用于设置左划出或右划出。
NaviagtionView中有两部分,上部分的header和下部分的menu,可在可在<NaviagtionView>标签中使用android:headerLayout和android:menu属性设置。但这两个部分也可以有不设置的,或都不设置。
<?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=".MainActivity"
tools:openDrawer="start"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Activity主体空间 !-->
</RelativeLayout>
<com.google.android.material.navigation.NavigationView
android:layout_width="250dp"
android:layout_height="match_parent"
android:id="@+id/navigationView"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_view_header_layout"
app:menu="@menu/navigation_view_menu"
/>
</androidx.drawerlayout.widget.DrawerLayout>
(3) 设置NavigationView菜单项监听及其他设置
// MainActivity.java
NavigationView navigationView=findViewById(R.id.navigationView);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
public boolean onNavigationItemSelected(MenuItem item) {
//选中菜单项执行
int menuItemId=item.getItemId();
return true;
}
});
//如为自定义菜单项,可进行子控件设置
//例:
Menu menu=navigationView.getMenu();
View menuItemView=menu.findItem(R.id.item1).getActionView();
ImageView imageView=menuItemView.findViewById(R.id.~);
imageView.setImageResource(R.drawable.~);
//设置NavigationView中header的子控件
//当只有一个header时,getHeaderView的参数index为0
View headerView=navigationView.getHeaderView(0);
TextView headerTextView=headerView.findViewById(R.id.navigation_view_head_textView);
headerTextView.setText("Str");
//DrawerLayout绘制布局显示NavigationView导航视图
DrawerLayout drawerLayout=findViewById(R.id.drawerLayout);
drawerLayout.openDrawer( GravityCompat.START );
drawerLayout.openDrawer( GravityCompat.END );
2. 显示自定义菜单项的菜单:
NavigationView支持显示自定义菜单项布局的菜单,用于替代只能显示黑色icon阴影图标与title的菜单。
在菜单项中添加app:actionLayout属性即可自定义菜单项布局。在设置本属性时请不要设置title,可能会导致冲突,可用tools:ignore="MenuTitle"替代title。
请注意是app:actionLayout不是android:actionLayout。
(1) 创建自定义菜单项的xml布局文件
// res\layout\menu_item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- 自定义菜单项 !-->
</RelativeLayout>
(2) 设置菜单项布局为自定义菜单项
在菜单项中添加app:actionLayout属性即可自定义菜单项布局。
<menu>中tools:showIn="navigation_view"可让预览图为菜单在导航视图中的样子。
// res\menu\navigation_view_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:showIn="navigation_view">
<item
android:id="@+id/item1"
app:actionLayout="@layout/menu_item_layout"
tools:ignore="MenuTitle" />
<item
android:id="@+id/item2"
app:actionLayout="@layout/menu_item_layout"
tools:ignore="MenuTitle"/>
</menu>
(3)设置自定义菜单项中的子控件及Header中的子控件
使用自定义菜单项时可使用navigationView.getMenu()获取菜单对象,使用menu.findItem()获取指定菜单项,然后使用getActionView()获取菜单项的View,最后使用view.findViewById()获取指定控件。
使用navigationView.getHeaderView(int index)获取Header的View对象,使用view.findViewById()获取指定控件。
// MainActivity.java
//如为自定义菜单项,可进行子控件设置
//例:
Menu menu=navigationView.getMenu();
View menuItemView=menu.findItem(R.id.item1).getActionView();
ImageView imageView=menuItemView.findViewById(R.id.~);
imageView.setImageResource(R.drawable.~);
//设置NavigationView中header的子控件
//当只有一个header时,getHeaderView的参数index为0
View headerView=navigationView.getHeaderView(0);
TextView headerTextView=headerView.findViewById(R.id.navigation_view_head_textView);
headerTextView.setText("Str");
3. 展开/关闭 DrawerLayout中的NavigationView
(1) Java代码展开
//DrawerLayout绘制布局显示NavigationView导航视图
DrawerLayout drawerLayout=findViewById(R.id.drawerLayout);
drawerLayout.openDrawer( GravityCompat.START );
drawerLayout.openDrawer( GravityCompat.END );
(2) 手势操作展开
长按边缘然后向中间划动。
(3) Java代码关闭
//DrawerLayout绘制布局显示NavigationView导航视图
DrawerLayout drawerLayout=findViewById(R.id.drawerLayout);
drawerLayout.closeDrawer( GravityCompat.START );
drawerLayout.closeDrawer( GravityCompat.END );
(4) 手势操作关闭
NavigationView向两边划动。
4. 常见的问题
(1) 监听器无法触发
NavigationItemSelectedListener失效可能是因为NavigationView在DrawerLayout中所处的位置无法接收到触碰事件。
请确保NavigationView位于DrawerLayout中所有控件的最后,确保它是 DrawerLayout 的最后一个子 View。这样可以确保 NavigationView 处于较高的 Z 轴顺序,使其能够响应触摸事件。
(2) Menu自定义布局不显示
NavigationView中的Menu如果使用自定义列表项布局,不显示的原因大概率是布局引用属性使用错误或未使用。
正确的使用方法是在<item中使用app:actionLayout="@layout/menu_item_layout"。请注意是app不是android,系统可能会建议android,请更改为app。
(3) Menu自定义布局重叠
NavigationView中的Menu如果使用自定义列表项布局,布局重叠的原因大概率是item中使用了title属性,删除该属性或用tools:ignore="MenuTitle"替代即可解决。
tag: 导航栏 , 绘制布局