【问题标题】:Override height of a single MenuItem in a NavigationView覆盖 NavigationView 中单个 MenuItem 的高度
【发布时间】:2018-06-06 01:31:29
【问题描述】:

我想在NavigationView 中增加single MenuItem 的高度。

我正在尝试将 Google MapFragment 放入项目的 actionLayout 中,如下所示,但我希望地图的高度更大。

有什么想法吗?

注意:

  • 我想利用 NavigationView 的标准菜单布局(我不希望像使用 this answer 那样实现整个自定义菜单布局)。
  • 我不想更改所有项(如this answer)的高度,只更改地图项。

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 ->
    ...
}

【问题讨论】:

  • 找到解决办法了吗

标签: android android-layout navigationview android-navigationview


【解决方案1】:

我最终通过创建一个可以做两件事的扩展函数来解决这个问题:

  1. 删除MenuItem的标题(即title = null
  2. 将状态更改侦听器附加到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 代码添加到答案中。
猜你喜欢
  • 2022-06-23
  • 2019-08-18
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
  • 2018-09-14
相关资源
最近更新 更多