需求
点击 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 聊聊, 查看更多联系方式