android - 覆盖 NavigationView 中单个 MenuItem 的高度
问题描述
我想增加单个 MenuItem
内部的高度NavigationView
。
我正在尝试将 GoogleMapFragment
放入项目中actionLayout
,如下所示,但我希望地图的高度更大。
有任何想法吗?
笔记:
activity_main_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:showIn="navigation_view">
...
<item
android:id="@+id/nav_map"
app:showAsAction="always"
android:title="@string/nav_map"
app:actionLayout="@layout/fragment_map" />
...
</menu>
fragment_map.xml
在这里调整android:layout_height
没有效果。
<?xml version="1.0" encoding="utf-8"?>
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:id="@+id/nav_map_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:mapType="normal"
map:liteMode="true"/>
在Activity.onCreate(...)
中MainActivity.kt
在动作视图上设置高度在这里没有效果。
val mapItem = nav.menu.findItem(R.id.nav_map)
// Has no effect: trying to set height to 128dp
mapItem.actionView.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 128)
// Hack: hide title
mapItem.title = null
val mapView = supportFragmentManager.findFragmentById(R.id.nav_map_fragment) as SupportMapFragment
mapView.getMapAsync { map ->
...
}
解决方案
我最终通过创建一个可以做两件事的扩展函数来解决这个问题:
MenuItem
删除(ietitle = null
)的标题- 将状态更改侦听器附加到
MenuItem
状态更改侦听器的目的是,当项目附加到窗口时,找到操作视图的父级并将其高度设置为WRAP_CONTENT
(并存储原始高度)。当视图分离时,它会恢复原来的高度。这是因为看起来视图实际上在您滚动时在不同项目之间回收......所以您会发现菜单中的所有项目逐渐受到影响,而不仅仅是您的目标项目。
扩展功能实现如下:
fun MenuItem.fillActionView() {
// Hide the title text
title = null
// Fill the action view
val thisView = actionView
thisView.addOnAttachStateChangeListener(object: View.OnAttachStateChangeListener {
private var originalHeight: Int? = null
override fun onViewAttachedToWindow(view: View?) {
if (view === thisView) {
val v = view?.parent?.parent as? View
if (v != null) {
v.layoutParams = v.layoutParams
.apply {
originalHeight = height
height = ViewGroup.LayoutParams.WRAP_CONTENT
}
}
}
}
override fun onViewDetachedFromWindow(view: View?) {
val h = originalHeight
val v = view?.parent?.parent as? View
if ((h != null) && (v != null)) {
v.layoutParams = v.layoutParams
.apply {
height = h
originalHeight = null
}
}
}
})
}
您可以onCreate()
像这样在活动中使用它:
val mapItem = nav.menu.findItem(R.id.nav_map) // Find your menu item which has the action view set
mapItem.fillActionView()
Java代码:
View.OnAttachStateChangeListener menuItemActionViewStateListener = new View.OnAttachStateChangeListener() {
int originalHeight = 0;
@Override
public void onViewAttachedToWindow(View v) {
View parent = (View) v.getParent();
if (parent != null)
parent = (View)parent.getParent();
if (parent != null) {
ViewGroup.LayoutParams p = parent.getLayoutParams();
originalHeight = p.height;
p.height = ViewGroup.LayoutParams.WRAP_CONTENT;
parent.requestLayout();
}
}
@Override
public void onViewDetachedFromWindow(View v) {
if (originalHeight != 0) {
View parent = (View) v.getParent();
if (parent != null)
parent = (View)parent.getParent();
if (parent != null) {
ViewGroup.LayoutParams p = parent.getLayoutParams();
p.height = originalHeight;
}
}
}
};
就像在这里一样使用它:
final View v = inflater.inflate(R.layout.main_menu_item, null);
v.addOnAttachStateChangeListener(menuItemActionViewStateListener);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menuItem.setActionView(v);
menuItem.setIcon(null);
menuItem.setTitle(null);
我希望这对其他人有帮助。
推荐阅读
- java - 如何将 gremlin 格式的 CSV 文件加载到 AWS Neptune
- python - 在python中使用漂亮的汤和硒来解析html
- qt - QML 项目可见性和计算
- python - 为什么 Tweepy 说转发是引用?
- javascript - 是否让循环内外使用相同
- javascript - JavaScript 闭包在这个示例案例中是如何工作的?
- java - 如何删除Java文件中特定单词的结尾?
- typescript - 在使用 vue 和 axios 创建的页面上显示列表
- php - JWT 实现中不受支持的声明
- spring-boot - 无法关闭 jms 侦听器,该侦听器使用 Runtime.exit、context.close、System.exit() 向 kafka spring boot 应用程序发布消息