Android 点击按钮显示悬浮菜单

更新日期: 2023-10-24 阅读次数: 721 字数: 731 分类: Android

需求

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

  • 时间设置
  • 语言设置等

Material Design Menu 组件

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

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

overflow, context, popup 的区别

Dropdown Menu 又细分为几种类型:

  • Overflow menu: 溢出菜单,即 Android 界面右上角三个点,点开后显示的菜单。所以触发显示是在 override fun onCreateOptionsMenu 中实现。
  • Context menu: 上下文菜单,或长按菜单。它是在用户长按某个视图元素(如按钮、列表项或图像)时显示的菜单。Context 菜单通常包含与所选视图元素相关的操作或选项。它可以在屏幕的任意位置显示,通常是靠近用户长按的视图元素。
  • Popup menu: 弹出菜单, Popup 菜单是一个与用户交互的弹出式菜单。它可以通过点击某个视图元素(如按钮)或调用代码来触发。Popup 菜单可以显示在屏幕的任意位置,通常是靠近触发它的视图元素,例如按钮。
  • List popup menu: 列表弹出菜单, List Popup 菜单是一个以列表形式显示的弹出菜单。于提供一个选择列表,用户可以从中选择一个或多个选项。List Popup 菜单可以显示在屏幕的任意位置,通常是靠近触发它的视图元素。它可以包含可滚动的列表项,并允许用户选择所需的选项。

很显然,我这里需要的是 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 的样式。

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式