Android 点击按钮显示悬浮菜单

发布时间: 2023-10-19 15:28:21 作者: 大象笔记

需求

点击 Android 屏幕上的设置按钮,弹出一个悬浮菜单,显示具体的细分配置功能。例如:

Material Design Menu 组件

https://github.com/material-components/material-components-android/blob/master/docs/components/Menu.md

也可用过输入框的下拉列表。

overflow, context, popup 的区别

Dropdown Menu 又细分为几种类型:

很显然,我这里需要的是 Popup Menu.

menu 布局文件

res/menu/popup_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/option_1"
          android:icon="@drawable/ic_3d_rotation_24dp"
          android:title="@string/option_1" />
    <item android:id="@+id/option_2"
          android:icon="@drawable/ic_accelerator_24dp"
          android:title="@string/option_2" />
    <item android:id="@+id/option_3"
          android:icon="@drawable/ic_favorite_24dp"
          android:title="@string/option_3" />
</menu>

显示菜单

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
	// ...

	binding.setting.setOnClickListener {
		showMenu(it, R.menu.popup_menu)
	}

	// ...
}

@RequiresApi(Build.VERSION_CODES.Q)
private fun showMenu(v: View, @MenuRes menuRes: Int) {
	val popup = PopupMenu(requireContext(), v, Gravity.RIGHT)
	popup.menuInflater.inflate(menuRes, popup.menu)

	// 点击事件,即,选中某个菜单
	popup.setOnMenuItemClickListener { item: MenuItem ->
		if (item.itemId == R.id.option_1) {
			Toast.makeText(requireContext(), "option_1", Toast.LENGTH_SHORT).show()
		} else if (item.itemId == R.id.option_2) {
			Toast.makeText(requireContext(), "option_2", Toast.LENGTH_SHORT).show()
		}
		true
	}

	popup.setForceShowIcon(true)  // 强制显示图标,默认不显示
	popup.show()
}

注意这里的 PopupMenu 是 android.widget.PopupMenu, 而不是 androidx 下的。

菜单位置

菜单弹出时,有个显示的问题,在右上角区域,菜单贴着屏幕的右边框,看起里很不舒服。

想让菜单的右边,与触发的按钮右边,垂直对齐。

参考:

https://developer.android.com/reference/android/widget/PopupMenu#PopupMenu(android.content.Context,%20android.view.View,%20int)

可以看到 PopupMenu 有三个构造函数,其中有支持 gravity 的,指定为 Gravity.RIGHT 即可。

val popup = PopupMenu(requireContext(), v, Gravity.RIGHT)

兼容性

在鸿蒙 3.0 平板系统上运行正常。

但是,在样式上还是有明显的差异:

原生 Android 系统右侧 padding 很大,而鸿蒙则没有足够的 padding,且 icon 很大不太协调。 下一步,开始尝试自定义 Popup Menu 的样式。

我是一名山东烟台的开发者,联系作者