Context-Menu.Android 详解:炫酷上下文菜单库
Android 原生的上下文菜单(ContextMenu)大家都用过——长按弹出一个朴素的列表,白底黑字,毫无设计感。如果你的 App 想做出 iOS 那种"长按弹出带图标动画的华丽菜单",原生 API 基本帮不了你。Context-Menu.Android 是知名开源团队 Yalantis 出品的一个库,专门解决这个问题:它提供了一个可高度定制的上下文菜单组件,支持图标、描述文字、动画效果,几行代码就能集成,让你的长按菜单从"系统默认"升级到"设计感拉满"。
GitHub 仓库:Yalantis/Context-Menu.Android。
1、Context-Menu.Android 是什么
Context-Menu.Android 是 Yalantis 开源的一个 Android UI 组件库,核心能力是在任意 View 上长按后,弹出一个带图标、带描述文字、带动画的"华丽版上下文菜单"。它不是对系统 ContextMenu 的封装,而是完全自绘的一套浮层菜单——你定义菜单项的图标和文字,库负责弹出动画、点击回调、背景模糊等视觉效果。
// 核心定位
Context-Menu.Android = 长按弹出 + 图标 + 动画 的自定义上下文菜单
// 它解决什么
// 原生 ContextMenu:白底黑字列表,无法加图标,无动画,设计感为零
// 第三方 PopupMenu:稍微好点,但仍然不支持图标、动画自定义
// Context-Menu.Android:每个菜单项可以有图标+描述,弹出有动画,背景可模糊
// 基本面
// 作者:Yalantis(知名 UI 开源团队,还有 Side-Menu.Android / Horizon / Phoenix 等)
// 形态:Android Library(Gradle 依赖或源码集成)
// 星标:3.8k+ Star(同类 UI 组件中相当受欢迎)2、核心概念:MenuObject 与 ContextMenuDialog
库的核心 API 非常简洁,两个概念够用:
// ① MenuObject:一个菜单项
// 每个菜单项包含:图标(Drawable)+ 可选的描述文字
val close = MenuObject().apply {
resource = R.drawable.ic_close // 图标
bgColor = Color.GRAY // 背景色
title = "关闭" // 可选描述
}
val share = MenuObject().apply {
resource = R.drawable.ic_share
bgColor = Color.BLUE
title = "分享"
}
val menuObjects = listOf(close, share)
// ② ContextMenuDialog:承载菜单的 Dialog
// 管理弹出动画、位置、点击回调
val menuDialog = ContextMenuDialogFragment(requireContext()).apply {
menuObjects = menuObjects // 设置菜单项列表
setOnMenuItemClickListener { position ->
// position 对应 menuObjects 的下标
when (position) {
0 -> { /* 关闭 */ }
1 -> { /* 分享 */ }
}
}
}MenuObject 是每个菜单项的"数据模型"——图标、背景色、标题、文字颜色都可单独定制。ContextMenuDialogFragment 是承载这些项的 Dialog Fragment,负责弹出动画和点击事件分发。两者配合,就构成了一个完整的上下文菜单。
3、集成与使用
// 方式一:Gradle 依赖
dependencies {
implementation 'com.github.Yalantis:Context-Menu.Android:1.1.0'
// 需先在 settings.gradle 或根 build.gradle 添加 JitPack 仓库:
// maven { url 'https://jitpack.io' }
}
// 方式二:直接拷贝源码(库本身不大,适合深度定制)
// clone 仓库 → 把 source 拷进你的项目 → 按需改动画/样式
// 使用流程
// 1. 创建 MenuObject 列表(定义菜单项)
// 2. 创建 ContextMenuDialogFragment,设置 menuObjects 和点击回调
// 3. 在需要弹出的地方调用 show()
// menuDialog.show(parentFragmentManager, "ContextMenu")
// 完整示例:在 RecyclerView item 长按时弹出
itemView.setOnLongClickListener {
menuDialog.show(parentFragmentManager, "ContextMenu")
true
}- 注意:该库较久未更新(最后 release 约 2018),在新版 AGP/AndroidX 下可能需要手动适配
- 如果 JitPack 依赖失败,建议用方式二(拷源码),改动量不大且可控
4、视觉效果与定制
Context-Menu.Android 之所以受欢迎,在于它的视觉效果远超原生,且定制程度高:
// 可定制项一览
MenuObject:
- resource(图标 Drawable)
- title(描述文字)
- titleColor(文字颜色)
- bgColor(菜单项背景色)
- bgDrawable(菜单项背景 Drawable,支持渐变/圆角/图片)
- textBgColor(文字区域背景)
- imgBgColor(图标区域背景)
- imgBgDrawable(图标区域背景 Drawable)
- menuTextSize(文字大小)
- direction(弹出方向:左右)
ContextMenuDialogFragment:
- 弹出动画(item 出现的顺序与节奏)
- 背景模糊(模糊宿主界面,凸显菜单)
- 菜单位置(可对齐到被长按 View 的坐标)
- 关闭动画一个常用的"高级感"搭配:每个 MenuObject 设不同 bgColor + 圆角 Drawable + 描述文字,让菜单看起来像一个彩色的"功能卡片堆"——这是 Yalantis 官方 demo 的经典效果,也是 3.8k Star 的来源。
5、长按触发与坐标对齐
上下文菜单的精髓是"长按哪里,菜单就在哪里弹出"。Context-Menu.Android 支持获取长按坐标并定位菜单,让它从被长按的 View 旁边弹出,而非固定在屏幕中央:
// 在 RecyclerView 的 ViewHolder 中
override fun onLongClick(v: View): Boolean {
// 记录长按坐标(在屏幕上的绝对位置)
val location = IntArray(2)
v.getLocationOnScreen(location)
val x = location[0] + v.width / 2 // View 中心 x
val y = location[1] // View 顶部 y
// 把坐标传给菜单 Dialog
menuDialog.setPosition(x, y) // 或用库提供的锚点机制
menuDialog.show(parentFragmentManager, "ContextMenu")
return true
}
// 库会根据坐标和 direction(弹出方向)
// 自动计算菜单的弹出位置和动画起点这套"长按 → 取坐标 → 定位弹出"的流程,是实现"iOS 式长按弹出菜单"的标准 Android 方案。Context-Menu.Android 把动画和定位都封装好了,你只管传坐标。
6、与原生 ContextMenu / PopupMenu 对比
方案 图标 描述文字 动画 背景模糊 自定义程度 设计感
------------------------------------------------------------------------------------
原生 ContextMenu 不支持 支持 无 无 低 朴素
PopupMenu 不支持 支持 基础 无 中 一般
Context-Menu.Android 支持 支持 丰富 支持 高 炫酷
自己手写 Dialog 支持 支持 自定义 自定义 最高 取决于你选型建议:如果你的菜单只需文字、不在意设计,原生 ContextMenu 或 PopupMenu 就够,省一个依赖;如果需要图标、动画、背景模糊,Context-Menu.Android 是最省事的选择——自己从零写一套带动画的浮层菜单至少两三天,用这个库十分钟集成完。如果对动画有极致要求且库满足不了,才考虑自己手写。
7、适用场景与局限
// 适合用 Context-Menu.Android 的场景
// - 图片/视频类 App:长按缩略图弹出"保存/分享/删除/收藏"
// - 社交/通讯录类:长按联系人 弹出"打电话/发短信/视频/拉黑"
// - 文件管理类:长按文件弹出"打开/复制/移动/删除/分享"
// - 任何"长按弹出带图标的操作菜单"的需求
// 局限性
// - 库较久未更新(2018 左右最后 release),未迁移 AndroidX
// - 新版 AGP/compileSdk 下可能需要手动修一些过时 API
// - 不支持 Compose(纯 View 体系,需手动桥接)
// - 动画使用属性动画,性能上不如 MotionLayout 灵活一个务实建议:把这个库当"源码参考"而非"黑盒依赖"——clone 下来、读一遍源码(代码量不大)、按需裁剪/修改,比直接依赖一个不再维护的库更可控。Yalantis 的代码质量很高,读它本身就是学习"如何写自定义浮层菜单"的优秀教材。
8、最佳实践与替代方案
- 推荐"拷源码集成"而非 Gradle 依赖,避免旧库在新环境下的兼容问题
- 图标用 VectorDrawable(SVG 矢量),避免分辨率适配问题
- 菜单项别超过 5 个:太多会超出屏幕、动画变慢、用户选择困难
- Compose 时代:如果项目已全面 Compose,考虑用 DropdownMenu + 自定义动画替代,Context-Menu.Android 本身不兼容 Compose
- 替代库:FloatingActionMenu、BoomMenu、CircularMenu 等,各有风格,按设计稿选
9、总结
Context-Menu.Android 是 Yalantis 出品的 Android 上下文菜单库,核心价值是把"长按弹出菜单"从朴素的白底列表,升级为带图标、带描述、带动画、可定制背景的炫酷浮层。API 简洁(MenuObject + ContextMenuDialogFragment),集成快,设计感拉满——尤其适合"图片/社交/文件管理"类 App 的长按操作场景。
关键要点:
- 定位:Yalantis 出品的自定义上下文菜单库,长按弹出带图标动画的浮层菜单
- 核心 API:MenuObject(定义菜单项)+ ContextMenuDialogFragment(承载与弹出)
- 可定制:图标、描述、背景色/Drawable、弹出方向、背景模糊、动画
- 注意:库较久未更新(2018),建议拷源码集成而非 Gradle 依赖
- Compose 项目需另寻方案(此库不兼容 Compose)
对于需要"长按弹出带图标动画菜单"的 Android 开发者而言,Context-Menu.Android 是一个"拿来即用 + 可学可改"的优秀选择。即使因为它的年龄而最终选择自己写,Yalantis 这套代码也是"如何实现自定义浮层菜单"的教科书级参考——动画怎么编排、坐标怎么对齐、点击怎么分发,读一遍就懂。好库的价值不只在于"省时间",还在于"教你思路"。
参考资料:
