先来一发效果图:

前面是返回效果,最后一下是实现home键的效果
前言
很久之前,就想做一个悬浮球了,毕竟是程序猿嘛,有想要的功能的时候总是想自己尝试一下,于是兴致勃勃的找了好久,都没有找到全局返回功能该如何实现!最后也无疾而终,就在前两天,又想到了这个功能,今天硬是花了好久,从一个同类软件获得了一点灵感,有一个关键的地方被我察觉到了,顺着这个思路找了很多资料,便实现了全局返回功能。
思路
废话不多说了,说说主要的思路吧,关键的一个类就是:AccessibilityService,官方文档地址,这个类与手机里面的一个功能密切相关:辅助功能-服务。官方文档来看,这个功能是为了方便有障碍的人士更好的使用手机。我们这里就不展开介绍里面的API了,为了实现我们的全局返回功能,我们只需要使用一个函数即可:boolean performGlobalAction (int action),官方解释如下:
Performs a global action. Such an action can be performed at any moment regardless of the current application or user location in that application. For example going back, going home, opening recents, etc.
翻译过来就是:
执行全局动作。无论该应用程序中的当前应用程序或用户位置如何,都可以随时执行此类操作。例如执行HOME键,BACK键,任务键等
其中可以传入的参数有四个:
从字面就可以理解,我们返回功能需要的就是GLOBAL_ACTION_BACK。所以我们只需要开启服务,调用函数就可以实现全局返回功能了。
编写代码
最重要的服务类
我们要新建一个类去继承自上面那个类:
public class MyAccessibilityService extends AccessibilityService {
public static final int BACK = 1;
public static final int HOME = 2;
private static final String TAG = "ICE";
@Override
public void onCreate() {
super.onCreate();
//使用EventBus代替广播
EventBus.getDefault().register(this);
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) { }
@Override
public void onInterrupt() {}
@Subscribe
public void onReceive(Integer action){
switch (action){
case BACK:
performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
break;
case HOME:
performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME);
break;
}
}
}
上面的onReceive方法是我们使用EventBus的订阅函数,当其他地方发送消息之后,我们这里就可以收到,然后判断是要执行后退还是回到桌面。
然后我们在AndroiManifest里面要注册我们的服务,但是这个注册的比较特殊:
首先加入权限声明:
复制代码 代码如下: <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"/>
然后注册服务:
<service android:name=".MyAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService"/> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice"/> </service>
其中resource中的内容我们要在xml包中声明,首先新建一个xml包,如下:
然后新建一个accessibilityservice.xml文件,内容如下:
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/start_floatingBall"/> <!--我这里写的是开启悬浮球功能-->
里面还可以设置许多属性,在这里就不介绍了,有兴趣的可以在官方文档里面查看。
到时候description的显示效果如下:
好了,到现在就已经完成了AccessibilityService服务的创建与注册了,接下来在Activity中启动服务就可以了: startService(new Intent(this,MyAccessibilityService.class));
使用EventBus传递事件即可实现返回:EventBus.getDefault().post(MyAccessibilityService.BACK);
但是要打开服务才行,简单办法是直接调用Intent跳到设置界面:startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
或者手动进入设置->辅助功能->服务->找到自己的app,然后开启服务即可。(不同的系统可能略有差异,小米就是在无障碍里面),界面如下:
悬浮球的简单实现
1.自定义一个View,画一个悬浮球:
public class FloatingView extends View {
public int height = 150;
public int width = 150;
private Paint paint;
public FloatingView(Context context){
super(context);
paint = new Paint();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(height,width);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画大圆
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
paint.setColor(getResources().getColor(R.color.state_one));
canvas.drawCircle(width/2,width/2,width/2,paint);
//画小圆圈
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
canvas.drawCircle(width/2,width/2, (float) (width*1.0/4),paint);
}
代码很简单,是画了一个大圆,然后一个小点的圆圈。
接下来,把这个view展示在桌面:
public class ViewManager {
FloatingView floatBall;
WindowManager windowManager;
public static ViewManager manager;
Context context;
private WindowManager.LayoutParams floatBallParams;
private ViewManager(Context context) {
this.context = context;
}
public static ViewManager getInstance(Context context) {
if (manager == null) {
manager = new ViewManager(context);
}
return manager;
}
public void showFloatBall() {
floatBall = new FloatingView(context);
windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
if (floatBallParams == null) {
floatBallParams = new WindowManager.LayoutParams();
floatBallParams.width = floatBall.width;
floatBallParams.height = floatBall.height;
floatBallParams.gravity = Gravity.TOP | Gravity.LEFT;
floatBallParams.type = WindowManager.LayoutParams.TYPE_TOAST;
floatBallParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
floatBallParams.format = PixelFormat.RGBA_8888;
}
windowManager.addView(floatBall, floatBallParams);
floatBall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post(MyAccessibilityService.BACK);
Toast.makeText(context, "点击了悬浮球 执行后退操作", Toast.LENGTH_SHORT).show();
}
});
floatBall.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
EventBus.getDefault().post(MyAccessibilityService.HOME);
Toast.makeText(context, "长按了悬浮球 执行返回桌面", Toast.LENGTH_SHORT).show();
return false;
}
});
}
public int getScreenWidth() {
return windowManager.getDefaultDisplay().getWidth();
}
}
为了简单起见,就没有贴上拖动悬浮窗的代码了,如有需要,可以在文章末尾查看源码。
上面代码把view加入到window中,并给view设置了点击事件,以及长按事件,向AccessibilityService传递消息,执行相应的事件。
要显示悬浮窗,要声明权限:
复制代码 代码如下:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
然后手动开启权限!不然无法显示悬浮窗。
最后我们在Activity中开启我们自定义的悬浮窗即可:
ViewManager.getInstance(MainActivity.this).showFloatBall();
结束语
现在看来,实现一个全局返回功能真的非常简单,但是当初就真的找了非常久,怎么找,怎么试都没法实现这个功能,于是尝试着去学学别的悬浮窗的代码,但是没办法,加壳了,反编译后没法看。但是我注意到了一个细节,它要我打开服务才能使用悬浮窗的功能,所以就从这里下手,慢慢找到了实现全局返回的方法。
源码地址:https://github.com/CHNicelee/FloatingBall
demo下载地址:FloatingBall_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# android全局悬浮球
# android
# 悬浮球
# Android全局返回
# Android 滑动返回Activity的实现代码
# Android 实现按两次返回键退出程序(两种方法)
# Android onKeyDown监听返回键无效的解决办法
# Android标题栏中添加返回按钮功能
# ionic2如何处理android硬件返回按钮
# Android悬浮按钮点击返回顶部FloatingActionButton
# Android 自定义返回按钮的实例详解
# 就可以
# 找了
# 新建一个
# 就不
# 自定义
# 只需要
# 文档
# 应用程序
# 自己的
# 的是
# 辅助功能
# 在这里
# 好了
# 就在
# 还可以
# 下载地址
# 说了
# 如有
# 最重要
# 不多
相关文章:
实例解析angularjs的filter过滤器
美食网站链接制作教程视频,哪个教做美食的网站比较专业点?
建站主机解析:虚拟主机配置与服务器选择指南
如何通过免费商城建站系统源码自定义网站主题与功能?
做企业网站制作流程,企业网站制作基本流程有哪些?
如何使用Golang table-driven基准测试_多组数据测量函数效率
定制建站方案优化指南:企业官网开发与建站费用解析
建站之星价格显示格式升级,你的预算足够吗?
内部网站制作流程,如何建立公司内部网站?
独立制作一个网站多少钱,建立网站需要花多少钱?
网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?
c++ stringstream用法详解_c++字符串与数字转换利器
PHP 500报错的快速解决方法
建站之星如何配置系统实现高效建站?
c++怎么使用类型萃取type_traits_c++ 模板元编程类型判断【方法】
如何用虚拟主机快速搭建网站?详细步骤解析
南京网站制作费用,南京远驱官方网站?
C#怎么创建控制台应用 C# Console App项目创建方法
C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)
如何在腾讯云服务器快速搭建个人网站?
一键网站制作软件,义乌购一件代发流程?
Bpmn 2.0的XML文件怎么画流程图
网站制作中优化长尾关键字挖掘的技巧,建一个视频网站需要多少钱?
香港服务器选型指南:免备案配置与高效建站方案解析
杭州银行网站设计制作流程,杭州银行怎么开通认证方式?
建站之星如何助力网站排名飙升?揭秘高效技巧
如何在西部数码注册域名并快速搭建网站?
如何在Golang中引入测试模块_Golang测试包导入与使用实践
如何基于云服务器快速搭建网站及云盘系统?
常州自助建站费用包含哪些项目?
香港服务器如何优化才能显著提升网站加载速度?
定制建站价位费用解析与套餐推荐全攻略
C#如何使用XPathNavigator高效查询XML
建站之星如何快速生成多端适配网站?
高端建站三要素:定制模板、企业官网与响应式设计优化
制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?
免费网站制作模板下载,除了易企秀之外还有什么H5平台可以制作H5长页面,最好是免费的?
如何快速生成可下载的建站源码工具?
Swift中switch语句区间和元组模式匹配
c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗
东莞专业制作网站的公司,东莞大学生网的网址是什么?
如何在阿里云高效完成企业建站全流程?
小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建
制作营销网站公司,淘特是干什么用的?
义乌企业网站制作公司,请问义乌比较好的批发小商品的网站是什么?
网站制作和推广的区别,想自己建立一个网站做推广,有什么快捷方法马上做好一个网站?
建站之星安装路径如何正确选择及配置?
Swift中swift中的switch 语句
网站制作报价单模板图片,小松挖机官方网站报价?
建站之星在线版空间:自助建站+智能模板一键生成方案
*请认真填写需求信息,我们会在24小时内与您取得联系。