android 添加随意拖动的桌面悬浮窗口,android 添加随意拖动的桌面悬浮窗口

用过新版本android 360手机助手都人都对 360中只在桌面显示一个小小悬浮窗口羡慕不已吧?

其实实现这种功能,主要有两步:

1.判断当前显示的是为桌面。这个内容我在前面的帖子里面已经有过介绍,如果还没看过的赶快稳步看一下哦。

2.使用windowManager往最顶层添加一个View

.这个知识点就是为本文主要讲解的内容哦。在本文的讲解中,我们还会讲到下面的知识点:

a.如果获取到状态栏的高度

b.悬浮窗口的拖动

c.悬浮窗口的点击事件

有开始之前,我们先来看一下效果图:

接下来我们来看看FloatView的代码:

代码如下:

public class FloatView extends ImageView{

private float mTouchX;

private float mTouchY;

private float x;

private float y;

private float mStartX;

private float mStartY;

private OnClickListener mClickListener;

private WindowManager windowManager = (WindowManager) getContext()

.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);

// 此windowManagerParams变量为获取的全局变量,用以保存悬浮窗口的属性

private WindowManager.LayoutParams windowManagerParams = ((FloatApplication) getContext()

.getApplicationContext()).getWindowParams();

public FloatView(Context context) {

super(context);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

//获取到状态栏的高度

Rect frame = new Rect();

getWindowVisibleDisplayFrame(frame);

int statusBarHeight = frame.top;

System.out.println("statusBarHeight:"+statusBarHeight);

// 获取相对屏幕的坐标,即以屏幕左上角为原点

x = event.getRawX();

y = event.getRawY() - statusBarHeight; // statusBarHeight是系统状态栏的高度

Log.i("tag", "currX" + x + "====currY" + y);

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN: // 捕获手指触摸按下动作

// 获取相对View的坐标,即以此View左上角为原点

mTouchX = event.getX();

mTouchY = event.getY();

mStartX = x;

mStartY = y;

Log.i("tag", "startX" + mTouchX + "====startY"

+ mTouchY);

break;

case MotionEvent.ACTION_MOVE: // 捕获手指触摸移动动作

updateViewPosition();

break;

case MotionEvent.ACTION_UP: // 捕获手指触摸离开动作

updateViewPosition();

mTouchX = mTouchY = 0;

if ((x - mStartX) < 5 && (y - mStartY) < 5) {

if(mClickListener!=null) {

mClickListener.onClick(this);

}

}

break;

}

return true;

}

@Override

public void setOnClickListener(OnClickListener l) {

this.mClickListener = l;

}

private void updateViewPosition() {

// 更新浮动窗口位置参数

windowManagerParams.x = (int) (x - mTouchX);

windowManagerParams.y = (int) (y - mTouchY);

windowManager.updateViewLayout(this, windowManagerParams); // 刷新显示

}

}

代码解释:

int statusBarHeight = frame.top;

为获取状态栏的高度,为什么在event.getRawY()的时候减去状态栏的高度呢?

因为我们的悬浮窗口不可能显示到状态栏中去,而后getRawY为获取到屏幕原点的距离。当我们屏幕处于全屏模式时,获取到的状态栏高度会变成0

(x - mStartX) < 5 && (y - mStartY) < 5

如果我们在触摸过程中,移动距离少于5 ,则视为点击,触发点击的回调。

另外我们需要自定义一个application:

代码如下:

public class FloatApplication extends Application {

private WindowManager.LayoutParams windowParams = new WindowManager.LayoutParams();

public WindowManager.LayoutParams getWindowParams() {

return windowParams;

}

}

代码解释:

自定义application的目的是为了保存windowParams的值 ,因为我们在拖动悬浮窗口的时候,如果每次都重新new一个layoutParams的话,在update

的时候会在异常发现。

windowParams的值也不一定非得在自定义application里面来保存,只要是全局的都行。

最后我们再来看看Activity中的实现。

代码如下:

public class MainActivity extends Activity implements OnClickListener{

private WindowManager windowManager = null;

private WindowManager.LayoutParams windowManagerParams = null;

private FloatView floatView = null;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_NO_TITLE);//取消标题栏

getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN ,

WindowManager.LayoutParams. FLAG_FULLSCREEN);//全屏

setContentView(R.layout.activity_main);

createView();

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.activity_main, menu);

return true;

}

public void onDestroy() {

super.onDestroy();

// 在程序退出(Activity销毁)时销毁悬浮窗口

windowManager.removeView(floatView);

}

private void createView() {

floatView = new FloatView(getApplicationContext());

floatView.setOnClickListener(this);

floatView.setImageResource(R.drawable.ic_launcher); // 这里简单的用自带的icon来做演示

// 获取WindowManager

windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);

// 设置LayoutParams(全局变量)相关参数

windowManagerParams = ((FloatApplication) getApplication()).getWindowParams();

windowManagerParams.type = LayoutParams.TYPE_PHONE; // 设置window type

windowManagerParams.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明

// 设置Window flag

windowManagerParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL

| LayoutParams.FLAG_NOT_FOCUSABLE;

/*

* 注意,flag的值可以为:

* LayoutParams.FLAG_NOT_TOUCH_MODAL 不影响后面的事件

* LayoutParams.FLAG_NOT_FOCUSABLE 不可聚焦

* LayoutParams.FLAG_NOT_TOUCHABLE 不可触摸

*/

// 调整悬浮窗口至左上角,便于调整坐标

windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP;

// 以屏幕左上角为原点,设置x、y初始值

windowManagerParams.x = 0;

windowManagerParams.y = 0;

// 设置悬浮窗口长宽数据

windowManagerParams.width = LayoutParams.WRAP_CONTENT;

windowManagerParams.height = LayoutParams.WRAP_CONTENT;

// 显示myFloatView图像

windowManager.addView(floatView, windowManagerParams);

}

public void onClick(View v) {

Toast.makeText(this, "Clicked", Toast.LENGTH_SHORT).show();

}

}

代码解释:

在activity中我们主要是添加悬浮窗,并且设置他的位置。另外需要注意flags的应用:

LayoutParams.FLAG_NOT_TOUCH_MODAL 不影响后面的事件

LayoutParams.FLAG_NOT_FOCUSABLE 不可聚焦

LayoutParams.FLAG_NOT_TOUCHABLE 不可触摸

最后我们在onDestroy()中移除到悬浮窗口。所以,我们测试的时候,记得按Home键来切换到桌面。

最后千万记得,在androidManifest.xml中来申明我们需要用到的android.permission.SYSTEM_ALERT_WINDOW权限

并且记得申明我们自定义的application哦。

AndroidManifest.xml代码如下:

代码如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526399.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android+版本升级的时候会清楚数据马,android主进程销毁了,线程会不会也销毁?...

Android Activity 销毁后子线程会不会被GC回收曾想当然地认为页面被finish之后线程会被android 虚拟机的垃圾回收机制回收掉。于是用页面跳转做测试测试代码结果有点意外&#xff0c;页面被销毁后定时器依然在执行。退出应用定时器还在执行。UI线程被结束掉&#xff0c;UI线程里…

mate7安装android o,华为Mate7升级安卓6.0详细教程

来讲一下华为Mate7升级安卓6.0(EMUI4.0)M版本详细图文教程吧&#xff0c;新的一年了&#xff0c;大家都迫不及待的想升级一下EMUI4.0&#xff0c;但是很多朋友都不知道怎样来升级&#xff0c;下面刷机网小编就来给大家仔细说一说吧&#xff0c;教程都在下面己经整理好了&#x…

html自动图片尺寸,关于html:CSS背景图像适合宽度,高度应按比例自动缩放

我有body {background: url(images/background.svg);}期望的效果是该背景图像的宽度等于页面的宽度&#xff0c;高度变化以保持比例。 例如 如果原始图像恰好是100 * 200(任何单位)且正文宽度为600px&#xff0c;则背景图像最终应为1200px高。 如果调整窗口大小&#xff0c;高度…

html定位的所有属性,HTML CSS定位属性详解 嘿嘿嘿

定位属性&#xff1a;Position作用&#xff1a;检索或者设置元素的定位方式“(改变元素位置)定位的步骤&#xff1a;1.给元素添加position属性 证明该元素要做位置变2.确定参照物&#xff01;(通过position的属性值来确定 )3.确定坐标 left right top bottomPosition的属性值&a…

html中表格与字对齐,html – 中心与表格单元格对齐

这是一个很好的起点。HTML&#xff1a;CSS&#xff1a;.containing-table {display: table;width: 100%;height: 400px; /* for demo only */border: 1px dotted blue;}.centre-align {padding: 10px;border: 1px dashed gray;display: table-cell;text-align: center;vertical…

postman响应html,Postman工具——请求与响应(示例代码)

两个内容&#xff1a; Request 请求和 Response 响应&#xff0c;下面就开始了。一、Request 请求Request 请求&#xff0c;我们只介绍常用的四种&#xff1a;GET、POST、PUT、DELETE&#xff0c;其他类型的就不展开介绍了。另外&#xff0c;我们今天测试的项目是基于 RESTful …

2021高考无准考证成绩查询,2021考研没有准考证号怎么查成绩

2021考研没有准考证号怎么查成绩2020-12-10 11:02:14文/徐克达考研初试结束后&#xff0c;大家最关心的就是成绩的事情了&#xff0c;那么考研没有准考证号怎么查成绩呢&#xff1f;下面是小编整理的详细内容&#xff0c;一起来看看吧&#xff01;考研没有准考证号查成绩的方法…

c++ 如何确认网卡为无线网卡_笔记本无线网卡有哪几种 有必要升级吗

无线网卡是很多朋友购买笔记本时容易忽视的部分&#xff0c;相比较处理器、内存、显卡和硬盘&#xff0c;无线网卡几乎不可选&#xff0c;而且很少有厂商提到自家产品采用的无线网卡型号。大家可能遇到过这种情况&#xff1a;为什么手机可以连接到5Ghz&#xff0c;而自己的笔记…

计算机网络专业运动会入场式,运动会入场式解说词(精选10篇)

运动会入场式解说词(精选10篇)在学习、工作生活中&#xff0c;接触并使用解说词的人越来越多&#xff0c;解说词是依靠文字来对事物、事件或人物进行描述的口头说明解说的词。大家知道解说词的格式吗&#xff1f;以下是小编精心整理的运动会入场式解说词(精选10篇)&#xff0c;…

gifcam使用缩小内存_Fedora 上的桌面环境内存占用测试 | Linux 中国

通常&#xff0c;根据功能、外观和其它品质&#xff0c;选择桌面是一件非常个人的偏好。但有时&#xff0c;你选择的桌面环境还会受到硬件限制。-- Troy DawsonFedora 中有 40 多种桌面环境(DE)。每种桌面环境都有自己的优点和缺点。通常&#xff0c;根据功能、外观和其它品质&…

优秀自我简介200字_全球战疫 翰墨传情——东方盛世杯网络公益书画展优秀作品【二】...

​本文纯手打原创&#xff0c;转发请标注出处&#xff01;中国书画爱好者&#xff0c;是中华优秀传统文化的薪火传承者。他们用生命中最美好的时光与最深沉的情感&#xff0c;实践着伟大文化复兴而不自知。——书画家网经过评委的精心评选&#xff0c;“东方盛世杯”2020网络公…

html渐变编织背景,【报Bug】uniapp设置了css渐变背景色编译时会报错

详细问题描述css样式中设置了背景色的话在H5发行编译时会报错&#xff0c;不过在浏览器运行编译时未发生错误。错误日志&#xff1a;[HBuilder] 15:14:32.364 Module build failed (from ./node_modules/postcss-loader/src/index.js):[HBuilder] 15:14:32.365 TypeError: Cann…

fi sap 凭证冲销 稅_SAP 成本收集器与重复制造配置手册

1&#xff0e;检查产品成本收集器的评估变式OPN22&#xff0e;检查产品成本收集器的成本核算变式OKKN3&#xff0e;确定作业数量的成本核算变式4&#xff0e;内部作业估价的成本核算变式5&#xff0e;定义订单交货的货物接收评估6&#xff0e;定义利润分析码OKG17&#xff0e;定…

要怎么在计算机里清除桌面内存,电脑内存不足怎么办?怎么清理电脑内存?

当电脑内存不足&#xff0c;内存占用高&#xff0c;磁盘空间不够时&#xff0c;我们该如何对电脑进行清理呢&#xff1f;今天我们就一起来看看清理电脑内存的方法&#xff01;一、结束进程中占用内存高的软件1.使用电脑组合键【CtrlShiftEsc】调出任务管理器&#xff0c;在【进…

python制作加密工具_Python制作钉钉加密/解密工具

又是很久没有写技术博客了&#xff0c;盖因最近都在学习知识&#xff0c;也没有总结出什么值得分享的内容&#xff0c;所以一直停笔至今。最近的工作和钉钉的开发打上了交到&#xff0c;官方并没有提供任何Python的SDK&#xff0c;于是只能全部自己写。现在我将其中实现起来相对…

计算机专业英语第07章,计算机专业英语 -第7章1.ppt

计算机专业英语 -第7章1Chapter 7 Input and Output Introduction Do you ever wonder how information gets into your computer and comes out in a form you can use? Input devices convert what we understand into what the system unit can process. Output devices co…

webform计算某几列结果_利用DataTable.Compute等方法和属性做各种统计(某一列的总和sum、不重复的某列记录数distinct)...

对应sql语句select UserID, UserName, UserMoney from Users从数据库里利用SqlDataAdapter读取出DataSet的方法不写了&#xff0c;这个好简单&#xff0c;写统计的办法using (DataTable dt ds.Tables[0]){//三个变量分别记录总记录数、不重复的用户数、所有用户的金额总额int …

山东科技大学计算机调剂难吗,山东科技大学 材料专业 调剂 求老师带走 国家线总分单科不都受限 - 考研 - 小木虫 - 学术 科研 互动社区...

佳木斯大学材料科学与工程学院接收2016年硕士研究生调剂信息佳木斯大学坐落于中国最佳生态环境魅力城市——黑龙江省佳木斯市&#xff0c;是黑龙江省重点建设高水平大学&#xff0c;其材料科学与工程学科为博士后科研流动站、博士学位授权学科和硕士学位授权学科&#xff0c;20…

quora html5,英语口语练习_Quora精选:外国人眼中5个最美英文单词_沪江英语

有人在国外知乎Quora上问“最美的英文单词是什么”。高票答案如下&#xff1a;Limerence纯爱The state of being infatuated or obsessed with another person, typically experienced involuntarily and characterized by a strong desire for reciprocation of one’s feelin…

axios传数组到后台_我是如何让公司后台管理系统焕然一新的

作者&#xff1a;yeyan1996https://juejin.im/post/5c76843af265da2ddd4a6dd0写在前面马上到了金三银四的时间&#xff0c;很多公司开启了今年第一轮招聘的热潮&#xff0c;虽说今年是互联网的寒冬&#xff0c;但是只要对技术始终抱有热情以及有过硬的实力&#xff0c;即使是寒…