NavigationView 自定义菜单项
NavigationView custom menu item
我正在尝试创建一个带有 header 和一些菜单项的抽屉。我已经将 header 创建为一个单独的布局,并将其放入 NavigationView 中,如下所示:
<com.google.android.material.navigation.NavigationView
android:id="@+id/navView"
android:layout_width="312dp"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header"
app:menu="@menu/menu_drawer">
header 正确显示。问题是默认情况下,菜单不可自定义。因此,我为菜单中的每个项目设置了 app:actionLayout="@layout/nav_menu_item"
属性,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group>
<item android:id="@+id/navDocumentScanItem"
app:actionLayout="@layout/nav_menu_item"
android:title="@null"/>
<item android:id="@+id/navReportItem"
app:actionLayout="@layout/nav_menu_item"
android:title="@null"/>
<item android:id="@+id/navHallOfFameItem"
app:actionLayout="@layout/nav_menu_item"
android:title="@null"/>
</group>
在我的 nav_menu_item 中,我有要用于抽屉菜单中每个项目的布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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/navItem"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="56dp">
<ImageView
android:id="@+id/navItemIcon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="6dp"
android:layout_marginStart="8dp"
android:layout_width="44dp"
android:layout_height="44dp"
tools:src="@drawable/nav_icon_qr_scan"/>
<TextView
android:id="@+id/navItemText"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/navItemIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/menu_item_text_style"
tools:text="Document Scanning"/>
</androidx.constraintlayout.widget.ConstraintLayout>
这看起来相当不错(如果我对其进行硬编码),但问题是我无法访问此自定义布局中的视图。如何获取 "navItemIcon" 和 "navItemText" 的句柄,以便我可以根据特定项目的项目位置以编程方式设置图标和文本?我需要在 activity 启动时修改这些,以便设置正确的文本和图标源。
谢谢!
我解决了 - 我使用 ViewTreeObserver 以编程方式更新项目。我会把解决方案留在这里,因为它可能会对某人有所帮助。
//handle the navigation drawer item
val navViewTreeObserver = navView.viewTreeObserver
navViewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
navView.viewTreeObserver.removeOnGlobalLayoutListener(this)
val menu = navView.menu
//get the menu items of the navigation view
for (i in 0 until menu.size()){
val menuItem = menu.getItem(i)
//get the relevant views that we want to change programmatically
val menuItemText = menuItem.actionView.findViewById<TextView>(R.id.navItemText)
val menuItemIcon = menuItem.actionView.findViewById<ImageView>(R.id.navItemIcon)
//change the menu item's text and icon depending on the position in the drawer
when (i){
0 -> {
menuItemText.text = "Document Scan"
menuItemIcon.setImageResource(R.drawable.nav_icon_qr_scan)
}
1 -> {
menuItemText.text = "Activity Reports"
menuItemIcon.setImageResource(R.drawable.nav_icon_report_inactive)
}
2 -> {
menuItemText.text = "Hall of fame"
menuItemIcon.setImageResource(R.drawable.nav_icon_hall_of_fame_inactive)
}
}
}
}
})
我正在尝试创建一个带有 header 和一些菜单项的抽屉。我已经将 header 创建为一个单独的布局,并将其放入 NavigationView 中,如下所示:
<com.google.android.material.navigation.NavigationView
android:id="@+id/navView"
android:layout_width="312dp"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header"
app:menu="@menu/menu_drawer">
header 正确显示。问题是默认情况下,菜单不可自定义。因此,我为菜单中的每个项目设置了 app:actionLayout="@layout/nav_menu_item"
属性,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<group>
<item android:id="@+id/navDocumentScanItem"
app:actionLayout="@layout/nav_menu_item"
android:title="@null"/>
<item android:id="@+id/navReportItem"
app:actionLayout="@layout/nav_menu_item"
android:title="@null"/>
<item android:id="@+id/navHallOfFameItem"
app:actionLayout="@layout/nav_menu_item"
android:title="@null"/>
</group>
在我的 nav_menu_item 中,我有要用于抽屉菜单中每个项目的布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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/navItem"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="56dp">
<ImageView
android:id="@+id/navItemIcon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="6dp"
android:layout_marginStart="8dp"
android:layout_width="44dp"
android:layout_height="44dp"
tools:src="@drawable/nav_icon_qr_scan"/>
<TextView
android:id="@+id/navItemText"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/navItemIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/menu_item_text_style"
tools:text="Document Scanning"/>
</androidx.constraintlayout.widget.ConstraintLayout>
这看起来相当不错(如果我对其进行硬编码),但问题是我无法访问此自定义布局中的视图。如何获取 "navItemIcon" 和 "navItemText" 的句柄,以便我可以根据特定项目的项目位置以编程方式设置图标和文本?我需要在 activity 启动时修改这些,以便设置正确的文本和图标源。
谢谢!
我解决了 - 我使用 ViewTreeObserver 以编程方式更新项目。我会把解决方案留在这里,因为它可能会对某人有所帮助。
//handle the navigation drawer item
val navViewTreeObserver = navView.viewTreeObserver
navViewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
navView.viewTreeObserver.removeOnGlobalLayoutListener(this)
val menu = navView.menu
//get the menu items of the navigation view
for (i in 0 until menu.size()){
val menuItem = menu.getItem(i)
//get the relevant views that we want to change programmatically
val menuItemText = menuItem.actionView.findViewById<TextView>(R.id.navItemText)
val menuItemIcon = menuItem.actionView.findViewById<ImageView>(R.id.navItemIcon)
//change the menu item's text and icon depending on the position in the drawer
when (i){
0 -> {
menuItemText.text = "Document Scan"
menuItemIcon.setImageResource(R.drawable.nav_icon_qr_scan)
}
1 -> {
menuItemText.text = "Activity Reports"
menuItemIcon.setImageResource(R.drawable.nav_icon_report_inactive)
}
2 -> {
menuItemText.text = "Hall of fame"
menuItemIcon.setImageResource(R.drawable.nav_icon_hall_of_fame_inactive)
}
}
}
}
})