# 高仿 flyme 悬浮球
## 前言
去年用了一整年的 MX4Pro,魅族留给我最大的印象就是悬浮球了(质量问题我就不说了),左右滑动切换应用、上拉返回桌面、下拉打开通知栏、轻触返回...,一切都那么丝滑。然而自从上半年换成了 s7dege,我感觉怎么也习惯不了没有悬浮球的生活了。
三星自己也有一个类似于悬浮球的功能,不过太过复杂,不易用,悬浮球本来就该是一个一步操作的产品,看来三星在软件设计方面还是任重而道远。于是乎我便在各大应用市场上找悬浮球,把所有排名靠前的悬浮球应用都安装试了一下,最后终于让我找到了一款几乎和 flyme 悬浮球相仿的 app。
![](https://www.writebug.com/myres/static/uploads/2021/11/23/77cdb46a0e6aec3453f4995e54e450a1.writebug)
这款 app 在我手机里呆了好几个月,是我手机里除了微信之外,唯一允许自启动的应用了。很感谢这款 app 的开发者,不仅没有任何广告,还非常好用,完美移植了 flyme 自带的悬浮球功能。
然而渐渐的,我便感觉到了一丝不舒服,那就是我每次安装了一个新 app,打开后提示要赋予权限(存储、拍照)的时候,6.0 的系统总会温馨的弹出一个框:
![](https://www.writebug.com/myres/static/uploads/2021/11/23/d8490e64f0a2468d16aac455491eede7.writebug)
然后我就必须到设置页面,花半天找到悬浮球,关掉它的“可出现在顶部的应用程”权限,然后才能回到 app,授予权限。最后,我还得再次跑到设置页面,再花半天找到悬浮球,打开它的“可出现在顶部的应用程”权限。朋友啊朋友,这种体验,一次就够了,然而硬是让我体验了 N 次啊!
然而有什么能难得倒程序员的呢?刚好这个周末在家无事,我决定按照自己的习惯,打造一个心目中最易用的悬浮球。
## 设计
### 1.UI
UI 很简单,直接用 sketch 切了三个圆,一个是作为背景的灰色半透明的圆,一个是中心的小圆,另外还有一个默认隐藏的大圆。
### 2.功能
因为自己的操作习惯是固定的,所以也就不需要给悬浮球添加自定义操作的功能了,直接将操作对应的功能写死即可。
(1)单击:返回
(2)长按:移动悬浮球
(3)左滑右滑:打开最近应用程序
(4)上拉:返回桌面
(5)下拉:
这块我最先开始定义的很简单,就是下拉通知栏,但是经过一天的使用,我又给它加了一个功能,就是保持下拉状态 1.5 秒,将移除悬浮球。这样你便可以很简单的移除掉悬浮球了。
## 实现
### 1.如何添加悬浮球到桌面
这里首先要感谢郭霖大神的 [《 Android 桌面悬浮窗效果实现,仿 360 手机卫士悬浮窗效果》](https://link.jianshu.com/?t=http://blog.csdn.net/guolin_blog/article/details/8689140),这部分我参考了这篇文章,成功的将悬浮球添加到了桌面。
```csharp
public static void addBallView(Context context) {
if (mBallView == null) {
WindowManager windowManager = getWindowManager(context);
int screenWidth = windowManager.getDefaultDisplay().getWidth();
int screenHeight = windowManager.getDefaultDisplay().getHeight();
mBallView = new FloatBallView(context);
LayoutParams params = new LayoutParams();
params.x = screenWidth;
params.y = screenHeight / 2;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity = Gravity.LEFT | Gravity.TOP;
params.type = LayoutParams.TYPE_PHONE;
params.format = PixelFormat.RGBA_8888;
params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
mBallView.setLayoutParams(params);
windowManager.addView(mBallView, params);
}
}
```
### 2.手势判断
这是最重要的部分了,承担着悬浮球的主要功能。
(1)手指按下时
按下时,隐藏小球,展现大球,并记录按下位置和按下时间。
```csharp
case MotionEvent.ACTION_DOWN:
mIsTouching = true;
mImgBall.setVisibility(INVISIBLE);
mImgBigBall.setVisibility(VISIBLE);
mLastDownTime = System.currentTimeMillis();
mLastDownX = event.getX();
mLastDownY = event.getY();
postDelayed(new Runnable() {
@Override
public void run() {
if (isLongTouch()) {
mIsLongTouch = true;
mVibrator.vibrate(mPattern, -1);
}
}
}, LONG_CLICK_LIMIT);
break;
```
代码最后的 postDealy 时干嘛使的呢?就是通过延迟 300 毫秒,判断是否是长按模式。如果目前还没有处于其他模式,则可判断为长按,并震动提醒。
(2)手指移动时
这时要判断是否是处于长按状态,如果是,那么进入 MOVE 模式,移动悬浮球,如果不是,则判断操作手势,即下拉还是上拉等其他手势。
```csharp
case MotionEvent.ACTION_MOVE:
if (!mIsLongTouch && isTouchSlop(event)) {
return true;
}
if (mIsLongTouch && (mCurrentMode == MODE_NONE || mCurrentMode == MODE_MOVE)) {
mLayoutParams.x = (int) (event.getRawX() - mOffsetToParent);
mLayoutParams.y = (int) (event.getRawY() - mOffsetToParentY);
mWindowManager.updateViewLayout(FloatBallView.this, mLayoutParams);
mBigBallX = mImgBigBall.getX();
mBigBallY = mImgBigBall.getY();
mCurrentMode = MODE_MOVE;
} else {
doGesture(event);
}
break;
```
进行手势操作的代码如下,主要是根据当前坐标与按下时记录的坐标进行计算,判断手势,并更新大球位置。
```cpp
private void doGesture(MotionEvent event) {
float offsetX = event.getX() - mLastDownX;
float offsetY = event.getY() - mLastDownY;
if (Math.abs(offsetX) < mTouchSlop && Math.abs(offsetY) < mTouchSlop) {
return;
}
if (Math.abs(offsetX) > Math.abs(offsetY)) {
if (offsetX > 0) {
if (mCurrentMode == MODE_RIGHT) {
return;
}
mCurrentMode = MODE_RIGHT;
mImgBigBall.setX(mBigBallX + OFFSET);
mImgBigBall.setY(mBigBallY);
} else {
if (mCurrentMode == MODE_LEFT) {
return;
}
mCurrentMode = MODE_LEFT;
mImgBigBall.setX(mBigBallX - OFFSET);
mImgBigBall.setY(mBigBallY);
}
} else {
if (offsetY > 0) {
if (mCurrentMode == MODE_DOWN || mCurrentMode == MODE_GONE) {
return;
}
mCurrentMode = MODE_DOWN;
mImgBigBall.setX(mBigBallX);
mImgBigBall.setY(mBigBallY + OFFSET);
//如果长时间保持下拉状态,将会触发移除悬浮球功能
postDelayed(new Runnable() {
@Override
public void run() {
if (mCurrentMode == MODE_DOWN && mIsTouching) {
toRemove();
mCurrentMode = MODE_GONE;
}
}
}, REMOVE_LIMIT);
} else {
if (mCurrentMode == MODE_UP) {
return;
}
mCurrentMode = MODE_UP;
mImgBigBall.setX(mBigBallX);
mImgBigBall.setY(mBigBallY - OFFSET);
}
}
}
```
(3)手指抬起时
手指抬起后,先要判断是否是长按模式,不是的话再判断是否是单击,都不是的话就根据当前状态触发对应功能。
```csharp
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mIsTouching = false;
if (mIsLongTouch) {
mIs
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
资源包含文件:设计报告word+项目源码 高仿flyme悬浮球,UI很简单,直接用sketch切了三个圆,一个是作为背景的灰色半透明的圆,一个是中心的小圆,另外还有一个默认隐藏的大圆。操作对应的功能写死,保持下拉状态1.5秒,将移除悬浮球,详细设计见设计报告word。 详细介绍参考:https://biyezuopin.blog.csdn.net/article/details/125481608
资源推荐
资源详情
资源评论
收起资源包目录
通过Java高仿flyme悬浮球设计.zip (44个子文件)
设计报告.docx 2.14MB
gradlew.bat 2KB
gradlew 5KB
gradle.properties 730B
LICENSE 1KB
app
proguard-rules.pro 670B
src
test
java
com
wangxiandeng
floatball
ExampleUnitTest.java 404B
androidTest
java
com
wangxiandeng
floatball
ExampleInstrumentedTest.java 756B
main
res
mipmap-xxxhdpi
ic_launcher.png 10KB
drawable-xhdpi
icon_bg.png 475B
icon_float.png 8KB
icon_big_ball.png 613B
icon_ball.png 1KB
mipmap-hdpi
ic_launcher.png 3KB
values
colors.xml 208B
strings.xml 244B
styles.xml 383B
dimens.xml 211B
mipmap-xxhdpi
ic_launcher.png 8KB
mipmap-mdpi
ic_launcher.png 2KB
mipmap-xhdpi
ic_launcher.png 5KB
layout
layout_ball.xml 1KB
activity_main.xml 1KB
xml
accessibilityservice.xml 230B
values-w820dp
dimens.xml 358B
java
com
wangxiandeng
floatball
FloatBallView.java 10KB
MainActivity.java 2KB
FloatWindowManager.java 2KB
AccessibilityUtil.java 2KB
FloatBallService.java 1KB
AndroidManifest.xml 1KB
app.iml 13KB
.gitignore 7B
build.gradle 874B
gradle
wrapper
gradle-wrapper.jar 52KB
gradle-wrapper.properties 233B
FLoatBall.iml 863B
.gitignore 15B
local.properties 470B
README.md 8KB
settings.gradle 15B
build
intermediates
dex-cache
cache.xml 9KB
generated
mockable-android-24.jar 31.96MB
build.gradle 498B
共 44 条
- 1
资源评论
shejizuopin
- 粉丝: 1w+
- 资源: 1300
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 获取CPU的序列号的Python脚本
- 4354图446546546546546
- 邮箱管理技巧:减少垃圾邮件的9项实用措施
- 三汇SMG 系列D 型模拟网关用户手册,用于三汇SMG系列网关配置
- Siemens Automation Framework V1.2
- 单个IO口检测多个按键
- 汇川EASY32x固件6.3.0.0
- 高分成品毕业设计《基于SSM(Spring、Spring MVC、MyBatis)+MySQL开发个人财务管理系统》+源码+论文+说明文档+数据库
- 高分成品毕业设计《基于SSM(Spring、Spring MVC、MyBatis)+MySQL开发B2C电子商务平台》+源码+论文+说明文档+数据库
- HKJC_3in1_TR_PROD_L3.0R1An_Build10229.apk
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功