android 悬浮框
来源:互联网 发布:python案例讲解 编辑:程序博客网 时间:2024/05/01 05:25
第二届 Google 暑期大学生博客分享大赛 – 2011 Android 成长篇
本文为参加Google暑期大学生博客分享大赛特别撰写。
—————————————————————-
大家对悬浮窗概念不会陌生,相信每台电脑桌面的右上角都会有这么一个东西,它总是出现在所有页面的顶端(Top Show)。但在Android平台中如何实现这样的效果呢?先来看一看效果图。
看见在Google搜索框上面的那个Icon图片了嘛。下面我就来详细介绍一下在Android平台下悬浮窗口的实现,并让它能够随手指的触摸而移动。
一、实现原理及移动思路
调用WindowManager,并设置WindowManager.LayoutParams的相关属性,通过WindowManager的addView方法创建View,这样产生出来的View根据WindowManager.LayoutParams属性不同,效果也就不同了。比如创建系统顶级窗口,实现悬浮窗口效果!然后通过覆写悬浮View中onTouchEvent方法来改变windowMananager.LayoutParams中x和y的值来实现自由移动悬浮窗口。
二、示例代码
先来看一看悬浮View的代码,这里用一个ImageView作为演示
01
public
class
MyFloatView
extends
ImageView {
02
private
float
mTouchStartX;
03
private
float
mTouchStartY;
04
private
float
x;
05
private
float
y;
06
07
private
WindowManager wm=(WindowManager)getContext().getApplicationContext().getSystemService(
"window"
);
08
//此wmParams变量为获取的全局变量,用以保存悬浮窗口的属性
09
private
WindowManager.LayoutParams wmParams = ((MyApplication)getContext().getApplicationContext()).getMywmParams();
10
11
public
MyFloatView(Context context) {
12
super
(context);
13
// TODO Auto-generated constructor stub
14
}
15
16
@Override
17
public
boolean
onTouchEvent(MotionEvent event) {
18
//获取相对屏幕的坐标,即以屏幕左上角为原点
19
x = event.getRawX();
20
y = event.getRawY()-
25
;
//25是系统状态栏的高度
21
Log.i(
"currP"
,
"currX"
+x+
"====currY"
+y);
22
switch
(event.getAction()) {
23
case
MotionEvent.ACTION_DOWN:
//捕获手指触摸按下动作
24
//获取相对View的坐标,即以此View左上角为原点
25
mTouchStartX = event.getX();
26
mTouchStartY = event.getY();
27
Log.i(
"startP"
,
"startX"
+mTouchStartX+
"====startY"
+mTouchStartY);
28
break
;
29
30
case
MotionEvent.ACTION_MOVE:
//捕获手指触摸移动动作
31
updateViewPosition();
32
break
;
33
34
case
MotionEvent.ACTION_UP:
//捕获手指触摸离开动作
35
updateViewPosition();
36
mTouchStartX=mTouchStartY=
0
;
37
break
;
38
}
39
return
true
;
40
}
41
42
private
void
updateViewPosition(){
43
//更新浮动窗口位置参数
44
wmParams.x=(
int
)( x-mTouchStartX);
45
wmParams.y=(
int
) (y-mTouchStartY);
46
wm.updateViewLayout(
this
, wmParams);
//刷新显示
47
}
48
49
}
上面的wmParams变量(即WindowManager.LayoutParams)的存储采用了extends Application的方式来创建全局变量,示例代码如下:
01
public
class
MyApplication
extends
Application {
02
03
/**
04
* 创建全局变量
05
* 全局变量一般都比较倾向于创建一个单独的数据类文件,并使用static静态变量
06
*
07
* 这里使用了在Application中添加数据的方法实现全局变量
08
* 注意在AndroidManifest.xml中的Application节点添加android:name=".MyApplication"属性
09
*
10
*/
11
private
WindowManager.LayoutParams wmParams=
new
WindowManager.LayoutParams();
12
13
public
WindowManager.LayoutParams getMywmParams(){
14
return
wmParams;
15
}
16
}
再来看一看Activity中的代码:
01
public
class
MyFloatViewActivity
extends
Activity {
02
/** Called when the activity is first created. */
03
04
private
WindowManager wm=
null
;
05
private
WindowManager.LayoutParams wmParams=
null
;
06
07
private
MyFloatView myFV=
null
;
08
09
10
@Override
11
public
void
onCreate(Bundle savedInstanceState) {
12
super
.onCreate(savedInstanceState);
13
setContentView(R.layout.main);
14
//创建悬浮窗口
15
createView();
16
17
}
18
19
20
21
private
void
createView(){
22
myFV=
new
MyFloatView(getApplicationContext());
23
myFV.setImageResource(R.drawable.icon);
//这里简单的用自带的Icom来做演示
24
//获取WindowManager
25
wm=(WindowManager)getApplicationContext().getSystemService(
"window"
);
26
//设置LayoutParams(全局变量)相关参数
27
wmParams = ((MyApplication)getApplication()).getMywmParams();
28
29
/**
30
*以下都是WindowManager.LayoutParams的相关属性
31
* 具体用途可参考SDK文档
32
*/
33
wmParams.type=LayoutParams.TYPE_PHONE;
//设置window type
34
wmParams.format=PixelFormat.RGBA_8888;
//设置图片格式,效果为背景透明
35
36
//设置Window flag
37
wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL
38
| LayoutParams.FLAG_NOT_FOCUSABLE;
39
/*
40
* 下面的flags属性的效果形同“锁定”。
41
* 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
42
wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL
43
| LayoutParams.FLAG_NOT_FOCUSABLE
44
| LayoutParams.FLAG_NOT_TOUCHABLE;
45
*/
46
47
48
wmParams.gravity=Gravity.LEFT|Gravity.TOP;
//调整悬浮窗口至左上角,便于调整坐标
49
//以屏幕左上角为原点,设置x、y初始值
50
wmParams.x=
0
;
51
wmParams.y=
0
;
52
53
//设置悬浮窗口长宽数据
54
wmParams.width=
40
;
55
wmParams.height=
40
;
56
57
//显示myFloatView图像
58
wm.addView(myFV, wmParams);
59
60
}
61
62
@Override
63
public
void
onDestroy(){
64
super
.onDestroy();
65
//在程序退出(Activity销毁)时销毁悬浮窗口
66
wm.removeView(myFV);
67
}
68
}
最后,别忘了在AndroidManifest.xml中添加权限:
1
<USES-PERMISSION android:name=
"android.permission.SYSTEM_ALERT_WINDOW"
/>
这样一个可以置顶显示、悬浮、且可自由移动的窗口就完工了。运行一下,然后按Home键返回桌面试试看(不能点击返回键,演示程序这里设置了销毁窗体)
三、一些说明
WindowManager的方法很简单,基本用到的就三个addView,removeView,updateViewLayout。
而WindowManager.LayoutParams的属性就多了,非常丰富,这个也是关键所在。
这里例举两个window type:
01
/**
02
* Window type: phone. These are non-application windows providing
03
* user interaction with the phone (in particular incoming calls).
04
* These windows are normally placed above all applications, but behind
05
* the status bar.
06
*/
07
public
static
final
int
TYPE_PHONE = FIRST_SYSTEM_WINDOW+
2
;
08
/**
09
* Window type: system window, such as low power alert. These windows
10
* are always on top of application windows.
11
*/
12
public
static
final
int
TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+
3
;
可以看出TYPE_SYSTEM_ALERT的显示层次比TYPE_PHONE还要高,有兴趣的可以试一试显示效果哦!
另外关键的window flag:
01
/** Window flag: this window won't ever get focus. */
02
public
static
final
int
FLAG_NOT_FOCUSABLE =
0x00000008
;
03
04
/** Window flag: this window can never receive touch events. */
05
public
static
final
int
FLAG_NOT_TOUCHABLE =
0x00000010
;
06
07
/** Window flag: Even when this window is focusable (its
08
* {@link #FLAG_NOT_FOCUSABLE is not set), allow any pointer events
09
* outside of the window to be sent to the windows behind it. Otherwise
10
* it will consume all pointer events itself, regardless of whether they
11
* are inside of the window. */
12
public
static
final
int
FLAG_NOT_TOUCH_MODAL =
0x00000020
;
详细的可以看一下这里。
最后,关于Android平台下的悬浮窗口,有人说很不友好,有人很困惑哪里会用到。事实上,在一些软件里面,悬浮窗口的设计给它们带来了很大的优势,比如流量监控,比如歌词显示。
- Android悬浮框应用--悬浮笔记
- Android 桌面悬浮框
- Android 桌面悬浮框
- Android桌面悬浮框
- android 悬浮框
- Android悬浮框
- Android 悬浮框实现
- Android悬浮框
- Android 悬浮编辑框
- android 悬浮框activity 二
- android 悬浮框service 三
- Android 悬浮框实现方法
- Android 悬浮框的实现
- Android仿360悬浮框
- Android-制作activity悬浮框
- android之桌面悬浮框
- android 悬浮框的实现
- Android 6.0授权悬浮框
- android 中Java和javascript的交互
- 初步试用Squid的替代产品──Varnish Cache网站加速器
- 使用Java线程堆栈分析问题
- Android 调用.NET Webservice无返回结果解决方案
- Nim游戏博弈(收集完全版)
- android 悬浮框
- 清除指定squid缓存文件的脚本
- 黑马程序员---网络编程技术
- 转载好用的小工具 【who-lock-me】
- platform_device内存,中断,时钟
- ubuntu下shell脚本运行异常:bash和dash的区别
- 京东怎么使用礼品卡购物
- 浅析android应用增量升级
- ARM7各种指令的周期数