当前位置: 首页 > 编程日记 > 正文

Activity悬浮并可拖动(访悬浮歌词)

强烈推荐:

最无私的Android资料(书籍+代码)分享-不要积分(求置顶)
http://www.eoeandroid.com/thread-80891-1-1.html

大量项目源码分享
http://www.eoeandroid.com/thread-162339-1-1.html

基于Android系统的影音播放器开发
http://www.eoeandroid.com/thread-183130-1-1.html

天天动听, 这款Android手机上的音乐播放器,相信不少朋友都曾用过。 不知大家是否注意到,天天动听有一个迷你歌词的特效。
什么效果呢? 就是不管你切到什么画面, 歌词永远显示,并且可以拖动。 类型QQ音乐,在电脑上播放时显示的歌词效果。
下面先来看一下效果。

这个歌词是在所有界面之上的。
下面我们将这个效果解剖一下, 我认为主要有三个难点:
1. 歌词悬浮在所有页面之上
2. 歌词可以拖动位置
3. 歌词的播放效果 (颜色覆盖)
对于第一点,首先想到的就是 WindowManager , 这个类可能不少人都用过, 一般用于获取屏幕宽度、高度,那么这次就要利用这个类来让我们的歌词永远置顶。
通过查看API,我们看到,在WindowManager.LayoutParams类中,有好几个属性可以设置View置顶。
引用

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之上。

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中添加权限:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>  

现在我们这样做,我们已经可以让歌词永远置顶了。 但是不要得意,现在这样,结果是我们TextView在最顶层了, 然后你就会发现,页面上什么操作都不能做了, 在TextView下面的任何东西,你都点不了。
为了解决这个,我们必须加上flags参数,让当前的View失去焦点,从而让后面的页面获得焦点。代码如下:

params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;

加上这一句就可以了。
好了,下面要处理的,就是让歌词可以移动。应该如何做呢? 我们知道,想要让一个View对象在页面上可以移动,只要实现其onTouchEvent事件即可。
  下面开始实现第二步: 歌词移动!
首先我们自定义一个TextView类:MyTextView, 该类继承自TextView, 并实现其中的onTouchEvent方法,来看一下代码:

@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坐标,否则拖动时会错位。

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);

其中下面三句是关键:

params.gravity=Gravity.LEFT|Gravity.TOP;   
幕左上角为原点,设置x、y初始值   
params.x = 0;   
params.y = 0;

现在这样的话,就可以实现View的移动了。
下面实现第三步: 歌词的播放效果。那么本例仅仅做一个循环, 实际音乐播放器要复杂些,需要根据歌剧的长度及时间间隔,来计算歌词的覆盖速度, 再根据这个速度来覆盖歌词,呈现给用户。要实现歌词播放的效果,需要用到画笔Paint, 还要用到Shader, 还有一个就是UI刷新的问题。一起来看下代码:

@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毫秒画一次, 就有了这个歌词播放的效果。

private Runnable update = new Runnable() {   
public void run() {   MyTextView.this.update();   handler.postDelayed(update, 3);   
}   private void update(){   postInvalidate();   
}  

转载于:https://www.cnblogs.com/vus520/archive/2012/08/01/2617977.html

相关文章:

实现单向访问控制

[Router]acl 3000 match-order auto //配置acl 3000[Router-acl3000]rule 1 deny icmp source 192.168.10.30 0.0.0.0 destination 192.168.10.20 0.0.0.0 icmp-type echo // 禁止主机PC2 ping主机PC1。[Router-acl3000]rule 2 deny tcp source 192.168.10.30 0.0.0.0 destin…

【直播】鱼佬:数据挖掘师之路(河北高校数据挖掘邀请赛)

数据挖掘师之路 目前 河北高校数据挖掘邀请赛 正在如火如荼的进行中。为了大家更好的参赛&#xff0c;王茂霖分享了 从0梳理1场数据挖掘赛事&#xff01;&#xff0c;完整梳理了从环境准备、数据读取、数据分析、特征工程到数据建模的整个过程。03月28日晚&#xff0c;王贺也为…

Python培训班线上线下哪种靠谱

Python近几年在人工智能领域的快速发展&#xff0c;引起了很多人的注意&#xff0c;各种Python培训机构也越来越多&#xff0c;很多零基础的同学都想通过报培训班学习&#xff0c;目前互联网的发达&#xff0c;Python培训分为线上和线下&#xff0c;那么Python培训班线上线下哪…

3-openstack之keystone上

3.1 keystone 安装linux-node1上面 3.2 配置源 12http://mirrors.aliyun.com/centos/7.2.1511/cloud/x86_64/openstack-newton/centos-release-openstack-newton-1-1.el7.noarch.rpm yumlocalinstall -y centos-release-openstack-newton-1-1.el7.noarch.rpm安装&#xff1a;…

全面认识一下.NET 4.0的缓存功能

很多关于.NET 4.0新特性的介绍&#xff0c;缓存功能的增强肯定是不会被忽略的一个重要亮点。在很多文档中都会介绍到在.NET 4.0中&#xff0c;缓存功能的增强主要是在扩展性方面做了改进&#xff0c;改变了原来只能利用内存进行缓存的局限&#xff0c;允许用户在不改变代码的情…

【直播】王茂霖:二手车交易价格预测 Baseline 提高(河北高校数据挖掘邀请赛)

二手车交易价格预测 Baseline 提高 目前 河北高校数据挖掘邀请赛 正在如火如荼的进行中。为了大家更好的参赛&#xff0c;王茂霖分享了 从0梳理1场数据挖掘赛事&#xff01;&#xff0c;完整梳理了从环境准备、数据读取、数据分析、特征工程到数据建模的整个过程。04月01日晚&a…

java培训要学习多久?

java技术要学习的内容有很多&#xff0c;那么究竟java培训要学习多久?这是很多同学都比较关注的一个问题&#xff0c;首先我们来详细的了解一下java培训的学习路线都有哪些&#xff0c;具体要花多少时间学习吧。  ​ java培训要学习多久? 1.Java语言介绍 从基础语法、面向对…

数据库范式温习

简介 关系数据库中的关系必须满足一定的要求&#xff0c;即满足不同的范式。 目前关系数据库有六种范式&#xff1a;第一范式&#xff08;1NF&#xff09;、第二范式&#xff08;2NF&#xff09;、第三范式&#xff08;3NF&#xff09;、第四范式&#xff08;4NF&#xff09;、…

使用 git 管理 portage tree

安装 git.备份原来的 portage tree.克隆 funtoo.cd /usr && rm -rf portage && git clone git://github.com/funtoo/portage.git 仓库中有gentoo.org, funtoo.org, master三个分支. 分支 gentoo.org 就是 gentoo 的官方 portage tree, 只不过是由 Daniel Robb…

02 Scratch等级考试(二级)模拟题

青少年编程竞赛交流群已成立&#xff08;适合6至18周岁的青少年&#xff09;&#xff0c;公众号后台回复【Scratch】或【Python】&#xff0c;即可进入。如果加入了之前的社群不需要重复加入。 微信后台回复“资料下载”可获取以往学习的材料&#xff08;视频、代码、文档&…

怎样找到适合自己的UI设计培训班

UI设计这个行业近几年有越来越多的人都比较关注&#xff0c;市面上的UI设计培训机构也越来越多&#xff0c;很多零基础同学都在寻找适合自己的UI设计培训机构&#xff0c;那么怎样找到适合自己的UI设计培训班呢?来 怎样找到适合自己的UI设计培训班? 一、看课程内容 UI设计行业…

Global.asax详解

在网上找了N多相关的东西总说的不够细,现在终于找到了.可以了解web.cofig和Global.asax之间的关系以及执行的顺序. 在Global.asax.cs文件中 protected void Application_BeginRequest(Object sender, EventArgs e){ Application["StartTime"] System.DateTime.Now…

Openfire服务器的安装部署

Openfire是一个强大的即时消息&#xff08;IM&#xff09;和聊天服务器&#xff0c;它实现了XMPP协议,可以使用它轻易的构建高效率的即时通信服务器. 其安装和部署都十分简单&#xff0c;并利用Web进行管理。单台服务器可支持上万并发用户&#xff0c;由于是采用开放的XMPP协议…

【直播】耿远昊:Pandas入门讲解(安泰第四届数据科学训练营)

Pandas入门讲解 直播信息 主讲人&#xff1a;耿远昊&#xff0c;Datawhale成员&#xff0c;joyful-pandas作者。 直播时间&#xff1a;2021年04月07日 20:00~21:00 直播内容&#xff1a; 时间序列中的必知必会&#xff1a;深入理解时间对象掌握滑动窗口熟悉重采样操作 直播…

女生参加软件测试培训合适吗

女生参加软件测试培训合适吗?这个问题困扰着很多女性朋友&#xff0c;大部分女性觉得软件测试属于IT技术行业&#xff0c;学起来是比较麻烦的&#xff0c;不知道是否适合女性&#xff0c;我们来看看下面的详细介绍。 女生参加软件测试培训合适吗?当然合适&#xff0c;如果说要…

三、概念数据模型CDM(Conceptual Database Model )

最后整理一下正确的是&#xff1a; 脚本1&#xff1a; .set_value(_First, true, new) .foreach_part(%Name%, "#") .if (%_First%) .delete(%CurrentPart%) .enddelete.set_value(_First, false, update) .else %CurrentPart% .endif .next 这个例子是把Name内容的…

【第11周复盘】小朋友们 100% 闯关成功!

「青少年编程竞赛交流群」已成立&#xff08;适合6至18周岁的青少年&#xff09;&#xff0c;公众号后台回复【Scratch】或【Python】&#xff0c;即可进入。如果加入了之前的社群不需要重复加入。 微信后台回复“资料下载”可获取以往学习的材料&#xff08;视频、代码、文档&…

keepalived and heartbeat

Keepalived使用的vrrp协议方式&#xff0c;虚拟路由冗余协议 (Virtual Router Redundancy Protocol&#xff0c;简称VRRP)&#xff1b;Heartbeat是基于主机或网络的服务的高可用方式&#xff1b;keepalived的目的是模拟路由器的双机heartbeat的目的是用户service的双机lvs的高可…

ui设计师要养成哪些职场习惯呢?

很多参加UI设计培训学完后的同学&#xff0c;都比较担心后期找工作的问题&#xff0c;不知道自己在职场中应该如何应对&#xff0c;小编本期为大家详细的介绍一下ui设计师要养成哪些职场习惯呢?希望能够帮助到大家在职场中更好的表现。 UI设计培训分享&#xff1a;ui设计师要养…

Html-Css 从入门到放弃(一)基础知识

注意要点&#xff1a; 1、ID属性不要以数字开头&#xff0c;数字开头的ID在 Mozilla/Firefox 浏览器中不起作用。 2、class 选择器用于描述一组元素的样式&#xff0c;class 选择器有别于id选择器&#xff0c;class可以在多个元素中使用。 3、不要在属性值与单位之间留有空格。…

六一:如何在Datawhale开源学习小程序中管

我们的组队学习马上就要开营了&#xff0c;本次组队学习与以往不同的是小程序中增加了队伍管理的功能。 为了方便大家组队&#xff0c;Datawhale的 六一同学 为大家准备了在Datawhale开源学习小程序中队伍管理的教程。 一、进入课程详情界面 1、打开小程序主页后&#xff0c…

C#让windows程序只运行一次

方法一&#xff1a;使用Mutex来进行1&#xff0e;首先要添加如下的namespace&#xff1a; using System.Threading;2&#xff0e;修改系统Main函数&#xff0c;大致如下&#xff1a; bool bCreatedNew;//Create a new mutex using specific mutex nameMutex m new Mutex(…

java培训分享:学习Java需要什么软件

在参加java培训过程中学习java技术&#xff0c;需要用到很多辅助工具&#xff0c;这些辅助工具是具有多功能性和实用性的&#xff0c;从代码构建到bug压缩。学习这些工具可以帮助您提高代码的质量&#xff0c;并成为一个更高效的Java开发人员。那么具体学习Java需要什么软件呢?…

J2SE基础夯实系列之数组

java中经常使用的是数组&#xff0c;前一段时间突然忘记了怎么定义char类型的二位数组&#xff1a; char[][] c {{},{},{A,B,C},{D,E,F},{G,H,I},{J,K,L},{M,N,O},{P,Q,R,S},{T,U,V},{W,X,Y,Z},};这个是char型的二维数组&#xff0c;思考一下&#xff0c;如果是定义String的二…

【组队学习】【24期】Datawhale组队学习内容介绍

第24期 Datawhale 组队学习活动马上就要开始啦&#xff01; 本次组队学习的内容为&#xff1a; 零基础入门语音识别&#xff08;食物声音识别&#xff09;Docker教程数据挖掘实践&#xff08;智慧海洋&#xff09;集成学习&#xff08;中&#xff09;河北邀请赛&#xff08;二…

centos5.6 (64bit)编译安装vsftpd-2.3.4的配置(两种用户登录)[连载之电子商务系统架构]...

centos5.6 (64bit)编译安装vsftpd-2.3.4的配置(两种用户登录)出处&#xff1a;http://jimmyli.blog.51cto.com/我站在巨人肩膀上Jimmy Li 作者&#xff1a;Jimmy Li关键词&#xff1a;电子商务&#xff0c;系统架构&#xff0c;vsftpd&#xff0c;本地用户登录&#xff0c;虚拟…

什么叫PMP?项目管理的本质是什么?

什么叫PMP?项目管理的本质是什么?相信有很多人现在对这个问题还不是非常了解&#xff0c;小编下面就为大家做下详细的介绍。 什么叫PMP?项目管理的本质是什么?什么叫PMP?PMP&#xff0c;中文全名是项目管理专业人士资格认证。 PMP是目前在项目管理这个领域认同度较高的一门…

基于C#的UDP协议的同步实现

一、摘要 总结基于C#的UDP协议的同步通信。 二、实验平台 Visual Studio 2010 三、实验原理 UDP传输协议同TCP传输协议的区别可查阅相关文档&#xff0c;此处不再赘述。 四、实例 4.1 采用socket实现UDP 由于UDP是一种无连接的协议。因此&#xff0c;为了使服务器应用能够发送和…

【直播】杨剑砺:数据可视化漫谈

数据可视化漫谈 目前 安泰第四届数据科学训练营 正在如火如荼的进行中。为了大家更好的学习&#xff0c;杨剑砺将为大家带来一场直播分享 —— 数据可视化漫谈。 直播信息 主讲人&#xff1a;杨剑砺&#xff0c;Datawhale成员&#xff0c;外企数据分析师。 直播时间&#xf…

service 与chkconfig

需要把启动脚本放到/etc/init.d/里面&#xff0c;还要加权限chmod x mysqld 本文转自flayber 51CTO博客&#xff0c;原文链接&#xff1a;http://blog.51cto.com/406647516/1919335&#xff0c;如需转载请自行联系原作者