Android项目之——Activity悬浮并可拖动(访悬浮歌词)
来源:互联网 发布:淘宝网中老年女上装 编辑:程序博客网 时间:2024/05/21 14:47
原文地址:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=188194
天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过。 不知大家是否注意到,天天动听有一个迷你歌词的特效。
什么效果呢? 就是不管你切到什么画面, 歌词永远显示,并且可以拖动。 类型QQ音乐,在电脑上播放时显示的歌词效果。
下面先来看一下效果。
这个歌词是在所有界面之上的。
下面我们将这个效果解剖一下, 我认为主要有三个难点:
1. 歌词悬浮在所有页面之上
2. 歌词可以拖动位置
3. 歌词的播放效果 (颜色覆盖)
对于第一点,首先想到的就是 WindowManager , 这个类可能不少人都用过, 一般用于获取屏幕宽度、高度,那么这次就要利用这个类来让我们的歌词永远置顶。
通过查看API,我们看到,在WindowManager.LayoutParams类中,有好几个属性可以设置View置顶。
引用
01
02
03
TYPE_SYSTEM_OVERLAYWindow type: system overlay windows, which need to be displayed on top of everything
else
.
TYPE_SYSTEM_ALERTWindow type: system window, such as low power alert.
TYPE_PHONEThese windows are normally placed above all applications, but behind the status bar.
下面我们来测试一下, 通过下面几句代码,就可以让一个View凌驾在所有View之上。
Java代码
01
02
03
04
05
06
07
08
09
WindowManager wm = (WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams params =
new
WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
TextView tv =
new
TextView(
this
);
wm.addView(tv, params);
这边需要注意的是, WindowManager也是通过 getSystemService 来获取,但必须先 getApplicationContext, 否则就无效了。
直接WindowManager wm = (WindowManager)getSystemService(WINDOW_SERVICE); 这样是无效的 !! 还有一点就是,别忘了在Manifest.xml中添加权限:
Java代码
01
<uses-permission android:name=
"android.permission.SYSTEM_ALERT_WINDOW"
/>
现在我们这样做,我们已经可以让歌词永远置顶了。 但是不要得意,现在这样,结果是我们TextView在最顶层了, 然后你就会发现,页面上什么操作都不能做了, 在TextView下面的任何东西,你都点不了。
为了解决这个,我们必须加上flags参数,让当前的View失去焦点,从而让后面的页面获得焦点。代码如下:
Java代码
01
params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
加上这一句就可以了。
好了,下面要处理的,就是让歌词可以移动。应该如何做呢? 我们知道,想要让一个View对象在页面上可以移动,只要实现其onTouchEvent事件即可。
下面开始实现第二步: 歌词移动!
首先我们自定义一个TextView类:MyTextView, 该类继承自TextView, 并实现其中的onTouchEvent方法,来看一下代码:
Java代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Override
public
boolean
onTouchEvent(MotionEvent event) {
//触摸点相对于屏幕左上角坐标
x = event.getRawX();
y = event.getRawY() - TOOL_BAR_HIGH;
Log.d(TAG,
"------X: "
+ x +
"------Y:"
+ y);
switch
(event.getAction()) {
case
MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
break
;
case
MotionEvent.ACTION_MOVE:
updatePosition();
break
;
case
MotionEvent.ACTION_UP:
updatePosition();
startX = startY =
0
;
break
;
}
return
true
;
}
//更新浮动窗口位置参数
private
void
updatePosition(){
// View的当前位置
params.x = (
int
)( x - startX);
params.y = (
int
) (y - startY);
wm.updateViewLayout(
this
, params);
}
其中getRawX、getRawY用于获取触摸点离屏幕左上角的距离。 而getX、getY用于获取触摸点离textView左上角的距离.两者相减,就是View左上角的坐标了。另外需要注意的是,在显示View这个View的时候,需要正确指定View的x,y坐标,否则拖动时会错位。
Java代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
WindowManager wm = (WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams params = MyTextView.params;
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT | WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
params.width = WindowManager.LayoutParams.FILL_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.alpha =
80
;
params.gravity=Gravity.LEFT|Gravity.TOP;
//以屏幕左上角为原点,设置x、y初始值
params.x =
0
;
params.y =
0
;
tv =
new
MyTextView(TopFrame.
this
);
wm.addView(tv, params);
其中下面三句是关键:
Java代码
01
02
03
04
params.gravity=Gravity.LEFT|Gravity.TOP;
幕左上角为原点,设置x、y初始值
params.x =
0
;
params.y =
0
;
现在这样的话,就可以实现View的移动了。
下面实现第三步: 歌词的播放效果。那么本例仅仅做一个循环, 实际音乐播放器要复杂些,需要根据歌剧的长度及时间间隔,来计算歌词的覆盖速度, 再根据这个速度来覆盖歌词,呈现给用户。要实现歌词播放的效果,需要用到画笔Paint, 还要用到Shader, 还有一个就是UI刷新的问题。一起来看下代码:
Java代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Override
protected
void
onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super
.onDraw(canvas);
float1 +=
0
.001f;
float2 +=
0
.001f;
if
(float2 >
1.0
){
float1 =
0
.0f;
float2 =
0
.01f;
}
this
.setText(
""
);
float
len =
this
.getTextSize() * text.length();
Shader shader =
new
LinearGradient(
0
,
0
, len,
0
,
new
int
[] { Color.YELLOW, Color.RED },
new
float
[]{float1, float2},
TileMode.CLAMP);
Paint p =
new
Paint();
p.setShader(shader);
// 下面这句才控制歌词大小
p.setTextSize(20f);
p.setTypeface(Typeface.DEFAULT_BOLD);
//此处x,y坐标也要注意,尤其是y坐标,要与字体大小协调
canvas.drawText(text,
0
,
20
, p);
}
再加上handler, 让他每隔3毫秒画一次, 就有了这个歌词播放的效果。
Java代码
01
02
03
04
05
06
07
08
09
10
private
Runnable update =
new
Runnable() {
public
void
run() {
MyTextView.
this
.update();
handler.postDelayed(update,
3
);
}
private
void
update(){
postInvalidate();
}
test2.rar(63.43 KB, 下载次数: 452)
- Android项目之——Activity悬浮并可拖动(访悬浮歌词)
- Android 悬浮Activity并可拖动(访悬浮歌词)
- Android 悬浮Activity并可拖动(访悬浮歌词)
- Android 悬浮Activity并可拖动(访悬浮歌词)
- Android 悬浮Activity并可拖动(访悬浮歌词)
- Android 悬浮Activity并可拖动(访悬浮歌词)
- Android 悬浮Activity并可拖动(访悬浮歌词)
- Android 悬浮Activity并可拖动(访悬浮歌词)
- Android项目之——Activity悬浮并可拖动
- Android项目之——Activity悬浮并可拖动
- Activity悬浮并可拖动(访悬浮歌词)
- Android 悬浮并可拖动的实现
- android中悬浮显示可拖动的歌词栏
- Android 悬浮在Activity内的可拖动View
- Android 可拖动可点击悬浮窗
- 可拖动悬浮窗
- Android 可随意拖动的悬浮窗体
- android WindowManager可拖动悬浮按钮
- 对于swc文件的动态加载
- Groovy探索 使用集合方法,写出更加Groovy风格的代码
- Android 的网络编程
- 重写控件时 getScrollX() 获取的值是
- View.VISIBLE、INVISIBLE、GONE的区别
- Android项目之——Activity悬浮并可拖动(访悬浮歌词)
- SJ9006: 在 IE6 IE7 IE8(Q) 中不能在 JSON 字符串或对象直接量的最后一个键值对后加 ','
- jdk环境变量的配置
- 图片上下滚动特效
- 算法导论 1.2-2
- 深入理解Java虚拟机读书笔记之:第6章 Java class文件
- BlackBerry 10使用Google TTS做中文文本朗读,开发语言C++ Qt Cascade
- 《C和指针》读书笔记(1)
- 基于MAXSCRIPT的模型导出插件技术