Переопределить высоту одного элемента MenuItem в NavigationView
Я хотел бы увеличить высоту одного MenuItem
внутри NavigationView
,
Я пытаюсь поставить гугл MapFragment
внутри предмета actionLayout
, как показано ниже, но я хочу, чтобы высота карты была больше.
Есть идеи?
Замечания:
- Я хочу использовать стандартную компоновку меню в NavigationView (я бы предпочел не использовать целую пользовательскую компоновку меню, используя этот ответ).
- Я не хочу изменять высоту всех элементов, таких как этот ответ, только элемент карты.
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 ->
...
}
1 ответ
Я решил эту проблему, создав функцию расширения, которая будет делать две вещи:
- Удалить заголовок
MenuItem
(т.е.title = 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);
Я надеюсь, что это полезно для других.