使用WindowManager添加View——悬浮窗口的基本原理
Android系统中的“窗口”类型虽然很多,但只有两大类是经常使用的:一是由系统进程管理的,称之为“系统窗口”;第二个就是由应用程序产生的,用于显示UI界面的“应用窗口”。如果大家熟悉WindowManagerService(窗口管理机制WMS)的话,那么一切都很简单。它是一个负责统筹管理所有窗口的一个服务,从始到终一直在运作。之所以扯上WMS,因为它才是大Boss,所有的窗口变化都要通知到它。而WindowManager虽然与它没有之间的关系,但是对它负责,所有信息会经过一定的途径传回到WMS中。额,跑题了,我们说的是WindowManager,它是一个接口类,它可以实现对view的管理,包括增加,更新和删除。
一、WindowManager
- 获取WindowManager
wManager = (WindowManager) getApplicationContext().getSystemService(
Context.WINDOW_SERVICE);在Activity和Service中都可以直接使用这个方法来获得WindowManager。其getSystemService返回的是一个WindowManagerImpl对象,这是一个存在于本地进程中的一个对象。而事实是WindowManagerImpl继承了WindowManager,而WindowManger继承了ViewManager。
- 设置WindowManager.LayoutParams
LayoutParams里面存放着的是窗口的属性,通过这个变量,可以为窗口赋予各式的属性。也可以改变它的属性值,来进行各种各样的操作,像悬浮窗口的拖动,拉伸等操作。
详细的属性表在:
http://www.cnblogs.com/shitianzeng/articles/2814050.html - WindowManager的操作
(1)窗口添加public void addView(View view, ViewGroup.LayoutParams params);
(2)窗口更新
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
(3)窗口删除
public void removeView(View view);
以上的三个方法都存在于ViewManager中。
二、悬浮窗实例
例子设计:利用service打开悬浮窗,其中放着一个自定义的View,点击消除悬浮窗。
- 首先是Service,它是由Activity打开。先获得WindowManager,再配置属性
public class WindowService extends Service implements OnClickListener { private WindowManager wManager;// 窗口管理者
private WindowManager.LayoutParams mParams;// 窗口的属性
private MyView myView;
private boolean flag = true; @Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
} @Override
public void onCreate() {
// TODO Auto-generated method stub
wManager = (WindowManager) getApplicationContext().getSystemService(
Context.WINDOW_SERVICE);
mParams = new WindowManager.LayoutParams();
mParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;// 系统提示window
mParams.format = PixelFormat.TRANSLUCENT;// 支持透明
//mParams.format = PixelFormat.RGBA_8888;
mParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;// 焦点
mParams.width = 490;//窗口的宽和高
mParams.height = 160;
mParams.x = 0;//窗口位置的偏移量
mParams.y = 0;
//mParams.alpha = 0.1f;//窗口的透明度
myView = new MyView(this);
myView.setOnClickListener(this);
super.onCreate();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
if (flag) {
flag = false;
wManager.addView(myView, mParams);//添加窗口
}
return super.onStartCommand(intent, flags, startId);
} @Override
public void onDestroy() {
// TODO Auto-generated method stub
if (myView.getParent() != null)
wManager.removeView(myView);//移除窗口
super.onDestroy();
} @Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v.equals(myView)) {
flag = true;
if (myView.getParent() != null)
wManager.removeView(myView);//移除窗口
}
} } - 一个自定义的view
很早以前写的surfaceView,里面包括文字图片的两个显示动画@SuppressLint("WrongCall")
public class MyView extends SurfaceView implements SurfaceHolder.Callback { private static int span = 5;
private MyThread wtf;
private Paint paint;
int sleepSpan = 150; // 动画的时延ms
Bitmap logo_s, logo_l; // logo图片引用
int width_s; // 图片大小
int height_s;
float currentX_s; // 图片位置
float currentY_s;
float currentX_l; // 图片位置
float currentY_l;
private Rect src;
private RectF dst;
private int currentAlpha = 0; public MyView(Context context) {
super(context); this.getHolder().addCallback(this);// 设置生命周期回调接口的实现者
paint = new Paint();// 创建画笔
paint.setAntiAlias(true);// 打开抗锯齿
} @Override
public void surfaceCreated(SurfaceHolder holder) {
logo_s = BitmapFactory
.decodeResource(getResources(), R.drawable.logo_s);
logo_l = BitmapFactory
.decodeResource(getResources(), R.drawable.logo_l);
// TODO Auto-generated method stub
width_s = logo_s.getWidth();
height_s = logo_s.getHeight();
src = new Rect(0, 0, 0, height_s);
// 大图片的位置
currentX_s = 5;
currentY_s = 5;
dst = new RectF(currentX_s, currentY_s, currentX_s, currentY_s
+ height_s);
currentX_l = currentX_s + width_s - logo_l.getWidth();
// 小图片的位置
currentY_l = currentY_s + height_s;
currentAlpha = 0;
wtf = new MyThread();
wtf.start();
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub } @Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub } @Override
public void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
// 绘制黑填充矩形清背景
super.onDraw(canvas); paint.setAlpha(120);// 设置不透明度为255
paint.setColor(Color.BLACK);// 设置画笔颜色
canvas.drawColor(Color.BLACK);
// 进行平面贴图
if (logo_s == null || logo_l == null)
return;
src.right += span;
dst.right += span;
canvas.drawBitmap(logo_s, src, dst, paint);
paint.setAlpha(currentAlpha);
canvas.drawBitmap(logo_l, currentX_l, currentY_l, paint);
// canvas.drawBitmap(bitmap, src, dst, paint);
/*
* Rect src = new Rect(x1, y2, cx1,cy1); Rect dst = new Rect(x2, y2,
* cx2, cy2); 第一个矩形,是你想截取的bitmap里面的哪一段。 第二个矩形,是你想显示在屏幕上的什么位置。
* 两个矩形可以不一样大小,在绘制的时候,会自动拉伸。
*/
} class MyThread extends Thread {
public void run() {
SurfaceHolder mholder = MyView.this.getHolder();// 获取回调接口
// 绘制tatans
try {
sleep(500);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
for (int i = 0; i <= width_s / span; i++) {
Canvas canvas = mholder.lockCanvas();// 获取画布
try {
synchronized (mholder) // 同步
{
onDraw(canvas);// 进行
}
sleep(20);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (canvas != null) {
mholder.unlockCanvasAndPost(canvas);
}
} }
// 绘制天坦智慧
for (int i = 0; i <= 25; i++) {
currentAlpha = i * 10;
Canvas canvas = mholder.lockCanvas();// 获取画布
try {
synchronized (mholder) // 同步
{
onDraw(canvas);// 进行
}
sleep(25);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (canvas != null) {
mholder.unlockCanvasAndPost(canvas);
}
} }
}
} }看看就行了
- Activity中,点击打开service
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Log.d("CPACM","onTouchEvent");
Intent intent = new Intent();
intent.setClass(this, WindowService.class);
startService(intent);
this.finish();
return super.onTouchEvent(event);
} - manifest.xml
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 使用SYSTEM_ALERT_WINDOW时必须要加 -->
- 效果图

三、结束语
学到越深,发现需要学的越多!
========================================
作者:cpacm
出处:(http://www.cnblogs.com/cpacm/p/4087690.html)
使用WindowManager添加View——悬浮窗口的基本原理的更多相关文章
- Android添加系统级顶层窗口 和 WindowManager添加view的动画问题
当Dialog有编辑框时如果选择会弹菜单窗口就不要用 Context applicationContext = mainActivity.getApplicationContext(); AlertD ...
- Android视频悬浮窗口实现
前言 本文例子实现了点击显示悬浮窗口,同时窗口可播放视频,拖动位置,点击关闭及返回APP页面,通过例子来讲述悬浮窗口实现原理及细节处理,效果图如下所示: 原理 WindowManager对View视图 ...
- Android之悬浮窗口实现(WindowManager)
工作中遇到一些项目需要把窗体显示在最上层,像来电弹窗显示电话号码等信息.拦截短信信息显示给用户或者游戏中实现声音的调节,我们想这些数据放在最上层,activity就满足不了我们的需求了,有些开发者使用 ...
- Android WindowManager和WindowManager.LayoutParams的使用以及实现悬浮窗口的方法
1.理清概念 我们使用过Dialog和PopupWindow,还有Toast,它们都显示在Activity之上.那么我们首先需要理解的是android中是如何去绘制这些UI的呢?这里我只讲我所理解的, ...
- WindowManager和WindowManager.LayoutParams的使用以及实现悬浮窗口的方法
写Android程序的时候一般用WindowManager就是去获得屏幕的宽和高,来布局一些小的东西.基本上没有怎么看他的其他的接口. 这两天想写一个简单的类似于Toast的东西,自定义布局,突然发现 ...
- Android悬浮窗口的实现
效果图:(悬浮框可拖动) 在项目开发中有一个需求:弹出悬浮窗后,响应悬浮窗的事件再弹出对话框,但是对话框怎么也不显示.也就是说在弹出悬浮框的同时,不能再弹出对话框,可能的原因: 1.悬浮框的焦点在最前 ...
- Android中悬浮窗口
调用WindowManager,并设置WindowManager.LayoutParams的相关属性,通过WindowManager的addView方法创建View,这样产生出来的View根据Wind ...
- Android中悬浮窗口的实现原理和示例代码
用了我一个周末的时间,个中愤懑就不说了,就这个问题,我翻遍全球网络没有一篇像样的资料,现在将实现原理简单叙述如下: 调用WindowManager,并设置WindowManager.LayoutPar ...
- Android 悬浮窗口
Android 悬浮窗口 一.创建悬浮窗口步骤 1.实现一个ViewGroup类,作为悬浮窗口的界面类,以便在里面重写onInterceptTouchEvent和onTouchEvent方法,实 ...
随机推荐
- hadoop 环境配置
HADOOP_HOME E:\tool\eclipse\hadoop-2.7.3 HADOOP_USER_NAME ambari-qa path: %HADOOP_HOME%/bin
- winform 外部组件发生异常
问题描述.先前程序运行可以正常,但是突然这次调试就弹出此异常: 解决方法:1.本次调试是不是重新生成解决方案了?应该是因为之前的解决方案删了,把引用的dll(包含此dll关联的dll)自动删掉: 2. ...
- 软工实践 - 第二十六次作业 Beta 冲刺(4/7)
队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10124816.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...
- android桌面悬浮窗仿QQ手机管家加速效果
主要还是用到了WindowManager对桌面悬浮进行管理. 需要一个火箭的悬浮窗 一个发射台悬浮窗 ,判断火箭是否放到了发射台,如果放上了,则使用AsyTask 慢慢将火箭的图片往上移.结束后., ...
- 搭建Hadoop环境(一)
我用SecureCRT作为客户端,链接虚拟机做的服务器,我用的桥接,所以把主机的一个端口映射到虚拟机22端口上去,
- 论 Web 前端加密的意义
论 Web 前端加密的意义 Web前端密码加密是否有意义? https://www.zhihu.com/question/25539382 https://blog.csdn.net/hla19910 ...
- Spark程序
Spark认识&环境搭建&运行第一个Spark程序 2017-07-09 17:17 by 牛仔裤的夏天, 181 阅读, 0 评论, 收藏, 编辑 摘要:Spark作为新一代大数据计 ...
- 【bzoj1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+权值线段树合并
题目描述 求一张图的严格次小生成树的边权和,保证存在. 输入 第一行包含两个整数N 和M,表示无向图的点数与边数. 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z ...
- HDU 6191 Query on A Tree(可持久化Trie+DFS序)
Query on A Tree Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Othe ...
- [bzoj2901]矩阵求和
题目大意:给出两个$n\times n$的矩阵,$m$次询问它们的积中给定子矩阵的数值和. 题解:令为$P\times Q=R$ $$\begin{align*}&\sum\limits_{i ...