| 特性 | 描述 |
|---|---|
| ✨ 轻量级 | 无第三方依赖,体积小巧 |
| 🎨 高度可定制 | 支持自定义背景、图标、菜单项、颜色等 |
| 📍 灵活定位 | 支持停靠在屏幕左侧或右侧 |
| 🔔 红点提醒 | 支持红点数字提醒功能 |
| 🎯 Unity 支持 | 兼容 Unity3D 游戏引擎 |
| 📱 Android 11+ | 支持最新 Android 版本 |
| 🔄 AndroidX | 完全兼容 AndroidX |
| ♿ 无障碍 | 完整的无障碍功能支持 |
在项目的 settings.gradle 中添加仓库:
dependencyResolutionManagement{repositories{maven{url ="https://maven.pkg.github.com/ColdBrando/FloatMenuSample" credentials{username ="你的GitHub用户名" password ="你的GitHub Token"// 或使用 GITHUB_TOKEN 环境变量 } } } }在 build.gradle 中添加依赖:
dependencies{implementation 'com.github.fanofdemo:FloatMenu:2.4.3' }注意: GitHub Token 需要有 read:packages 权限。
无需配置仓库,直接添加依赖:
dependencies{implementation 'com.github.ColdBrando:FloatMenuSample:v2.4.0' }在 settings.gradle 中添加:
repositories{maven{url 'https://jitpack.io' } }将 FloatMenu 模块复制到你的项目:
# 克隆项目 git clone https://github.com/ColdBrando/FloatMenuSample.git # 复制 FloatMenu 模块到你的项目 cp -r FloatMenuSample/FloatMenu your-project/在 settings.gradle 中添加:
include ':FloatMenu'在 build.gradle 中添加:
dependencies{implementation project(':FloatMenu') }// 1. 创建菜单项List<FloatItem> items = newArrayList<>(); items.add(newFloatItem("首页", R.drawable.icon_home)); items.add(newFloatItem("客服", R.drawable.icon_service)); items.add(newFloatItem("消息", R.drawable.icon_msg)); // 2. 创建并显示悬浮菜单FloatMenu.create(this) .logo(R.drawable.logo) .items(items) .show();FloatMenu.create(this) .logo(R.drawable.logo) .items(items) .listener(newFloatMenuView.OnMenuClickListener(){@OverridepublicvoidonItemClick(intposition, Stringtitle){Toast.makeText(this, "点击了: " + title, Toast.LENGTH_SHORT).show()} @Overridepublicvoiddismiss(){// 菜单关闭回调 } }) .show();FloatMenu.create(context) .logo(R.drawable.logo) .items(items) .location(FloatMenu.LEFT) // 停靠在左侧 .autoShrink(5000) // 5秒后自动贴边 .showRedDot(true) // 显示红点数字 .backgroundColor(0xFF4CAF50) // 自定义背景颜色 .drawCircleBg(true) // 绘制圆形背景 .listener(listener) .show();┌─────────────┐ │ 贴边状态 │ ──点击──> ┌─────────────┐ │ (50%隐藏) │ │ 正常状态 │ └─────────────┘ └─────────────┘ │ 点击 ↓ ┌─────────────┐ │ 展开状态 │ └─────────────┘ 悬浮球在拖动时始终保持在屏幕边界内:
- X轴范围:
[0, 屏幕宽度 - logo宽度] - Y轴范围:
[状态栏高度, 屏幕高度 - logo高度] - 手指中心与logo圆心保持一致
可配置延时后自动贴边至屏幕边缘:
- 默认 3 秒后自动贴边
- 贴边后 logo 的 50% 在屏幕内,50% 超出边界
- 使用平滑动画过渡(300ms 贴边,200ms 恢复)
| 状态 | 描述 |
|---|---|
| 正常状态 | logo 完全可见,可点击展开菜单 |
| 贴边状态 | logo 的 50% 超出屏幕,点击先恢复 |
| 展开状态 | 菜单已展开,点击 logo 关闭菜单 |
| 拖动状态 | 正在拖动中,暂停贴边计时 |
在 Service 中使用悬浮菜单可以让菜单在应用外持续显示。
<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW" />publicclassFloatMenuServiceextendsService{privateFloatLogoMenumFloatMenu; @OverridepublicvoidonCreate(){super.onCreate(); initFloatMenu()} @OverridepublicintonStartCommand(Intentintent, intflags, intstartId){if (mFloatMenu != null){mFloatMenu.show()} returnSTART_STICKY} @OverridepublicvoidonDestroy(){super.onDestroy(); if (mFloatMenu != null){mFloatMenu.destroyFloat()} } privatevoidinitFloatMenu(){List<FloatItem> items = newArrayList<>(); items.add(newFloatItem("首页", R.drawable.icon_home)); mFloatMenu = FloatMenu.create(getApplicationContext()) .logo(R.drawable.logo) .items(items) .location(FloatMenu.LEFT) .show()} }<serviceandroid:name=".FloatMenuService"android:enabled="true"android:exported="false" />// 启动服务Intentintent = newIntent(this, FloatMenuService.class); startService(intent); // 停止服务Intentintent = newIntent(this, FloatMenuService.class); stopService(intent);| 方法 | 必须 | 默认值 | 说明 |
|---|---|---|---|
logo(int resId) | ✅ | - | 设置 logo 图标(资源 ID) |
logo(Bitmap bitmap) | ✅ | - | 设置 logo 图标(Bitmap) |
items(List<FloatItem>) | ✅ | - | 设置菜单项列表 |
listener(OnMenuClickListener) | ⭕ | null | 设置点击监听器 |
location(int) | ⭕ | RIGHT | 停靠位置(LEFT/RIGHT) |
autoShrink(int) | ⭕ | 3000 | 自动贴边延时(0=不贴边) |
showRedDot(boolean) | ⭕ | false | 是否显示红点数字 |
drawCircleBg(boolean) | ⭕ | true | 是否绘制圆形背景 |
backgroundColor(int) | ⭕ | 系统默认 | 背景颜色 |
backgroundDrawable(Drawable) | ⭕ | 系统默认 | 背景 Drawable |
show() | ✅ | - | 显示悬浮菜单 |
// 方法1:只有标题FloatItem(Stringtitle) // 方法2:标题 + 图标资源IDFloatItem(Stringtitle, intdrawableId) // 方法3:标题 + 图标BitmapFloatItem(Stringtitle, Bitmapbitmap) // 方法4:完整参数FloatItem(Stringtitle, intpressColor, intnormalColor, Bitmapicon, StringdotNum)publicclassMyFloatDialogextendsBaseFloatDialog{@OverridepublicViewonCreateView(LayoutInflaterinflater){Viewview = inflater.inflate(R.layout.my_float_dialog, null); returnview} } // 使用MyFloatDialogdialog = newMyFloatDialog(); dialog.show(this);BaseFloatDialogdialog = newBaseFloatDialog(this, newBaseFloatDialog.GetViewCallback(){@OverridepublicViewonCreateView(LayoutInflaterinflater){Viewview = inflater.inflate(R.layout.my_float_dialog, null); // 初始化视图returnview} }); dialog.show();| 使用场景 | 权限要求 |
|---|---|
| 应用内悬浮 | 无需权限 |
| 桌面悬浮 | SYSTEM_ALERT_WINDOW |
添加悬浮窗权限:
<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW" />| 项目 | 要求 |
|---|---|
| 最低 SDK | API 11 (Android 3.0) |
| 编译 SDK | API 36 |
| Java 版本 | Java 17 |
| Gradle 版本 | 8.5+ |
查看 FloatMenuDemo 模块了解完整用法。
Demo 应用展示了:
- ✅ Activity 中使用悬浮菜单
- ✅ Service 中使用悬浮菜单
- ✅ 自定义配置
- ✅ 生命周期管理
新增功能
- 简化的 FloatMenu API,提供链式调用
- 新增 FloatMenuService 支持 Service 中使用悬浮菜单
- 新增动态配置方法
setLogoDrawNum()和setLogoDrawBg()
Bug 修复
- 修复右侧菜单展开时跳到左侧的问题
- 修复菜单展开后 logo 背景消失的问题
- 修复 lint 警告和无障碍支持
优化
- 移除 logo 拖动时的旋转动画
- 统一背景颜色
- 代码重构,简化定位逻辑
查看 完整更新日志
欢迎提交 Issue 和 Pull Request!
详情请参阅 贡献指南
BSD 3-Clause License Copyright (c) 2016, Shanghai YUEWEN Information Technology Co., Ltd. All rights reserved. 详细内容见项目根目录的 LICENSE 文件。
- 作者:ColdBrando
- 邮箱:[email protected]
如果这个项目对你有帮助,请给个 ⭐️ Star 支持一下!
