android 悬浮窗半隐藏开发怎样让悬浮Activity只是隐藏而不销毁

Android中加入悬浮窗 -
- ITeye博客
博客分类:
悬浮窗可以一直在前台显示一些信息,无论当前的Activity是哪个应用的。比如显示当前的上下行网速等
import android.app.S
import android.content.BroadcastR
import android.content.C
import android.content.I
import android.graphics.PixelF
import android.graphics.R
import android.os.IB
import android.view.G
import android.view.LayoutI
import android.view.MotionE
import android.view.V
import android.view.WindowM
import android.view.View.OnTouchL
import android.view.WindowManager.LayoutP
* 悬浮窗Service 该服务会在后台一直运行一个悬浮的透明的窗体。
public class FloatingService extends Service {
private int statusBarH// 状态栏高度
private V// 透明窗体
private boolean viewAdded =// 透明窗体是否已经显示
private WindowManager windowM
private WindowManager.LayoutParams layoutP
public IBinder onBind(Intent intent) {
public void onCreate() {
super.onCreate();
view = LayoutInflater.from(this).inflate(R.layout.floating, null);
windowManager = (WindowManager) this.getSystemService(WINDOW_SERVICE);
* LayoutParams.TYPE_SYSTEM_ERROR:保证该悬浮窗所有View的最上层
* LayoutParams.FLAG_NOT_FOCUSABLE:该浮动窗不会获得焦点,但可以获得拖动
* PixelFormat.TRANSPARENT:悬浮窗透明
layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT, LayoutParams.TYPE_SYSTEM_ERROR,
LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
// layoutParams.gravity = Gravity.RIGHT|Gravity.BOTTOM; //悬浮窗开始在右下角显示
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
view.setOnTouchListener(new OnTouchListener() {
float[] temp = new float[] { 0f, 0f };
public boolean onTouch(View v, MotionEvent event) {
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_DOWN: // 按下事件,记录按下时手指在悬浮窗的XY坐标值
temp[0] = event.getX();
temp[1] = event.getY();
case MotionEvent.ACTION_MOVE:
refreshView((int) (event.getRawX() - temp[0]), (int) (event
.getRawY() - temp[1]));
* 刷新悬浮窗
* @param x
拖动后的X轴坐标
* @param y
拖动后的Y轴坐标
public void refreshView(int x, int y) {
//状态栏高度不能立即取,不然得到的值是0
if(statusBarHeight == 0){
View rootView
= view.getRootView();
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
statusBarHeight = r.
layoutParams.x =
// y轴减去状态栏的高度,因为状态栏不是用户可以绘制的区域,不然拖动的时候会有跳动
layoutParams.y = y - statusBarH//STATUS_HEIGHT;
refresh();
* 添加悬浮窗或者更新悬浮窗 如果悬浮窗还没添加则添加 如果已经添加则更新其位置
private void refresh() {
if (viewAdded) {
windowManager.updateViewLayout(view, layoutParams);
windowManager.addView(view, layoutParams);
viewAdded =
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
refresh();
* 关闭悬浮窗
public void removeView() {
if (viewAdded) {
windowManager.removeView(view);
viewAdded =
public void onDestroy() {
super.onDestroy();
removeView();
class StatusBarReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
//intent.get
floating.xml
&?xml version="1.0" encoding="UTF-8"?&
&LinearLayout xmlns:android="/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
&!-- android:updatePeriodMillis="10000"& --&
&LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/floating"
android:gravity="center_vertical"
&ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:src="@drawable/upload"/&
android:id="@+id/flowing"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:gravity="right"
android:text="0K/s"
android:textColor="#000000"
&ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:src="@drawable/download"/&
android:gravity="right"
android:id="@+id/flowspeed"
android:paddingRight="10.0dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="17K/s"
android:textColor="#000000"
&/LinearLayout&
&ImageButton
android:id="@+id/floating_button_hide"
android:background="@drawable/floatingwindowhidebutton"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="\?android:buttonStyleSmall" /&
&/LinearLayout&
最后还要在AndroidManifest.xml加一个权限
&!-- 悬浮窗(FloatingService) permission --&
&uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /&
浏览 27532
easion_zms
浏览: 73863 次
来自: 珠海
09-10 03:56:07.128: D/LogServic ...
&div class=&quote_title ...
成功,楼主好厉害。接下来看看咋用吧
垃圾残品,发出来很好玩的样子
&div class=&quote_title ...Android 悬浮Activity并可拖动(访悬浮歌词) - thinkfeed - ITeye博客
博客分类:
天天动听, 这款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方法,来看一下代码:
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();
case MotionEvent.ACTION_MOVE:
updatePosition();
case MotionEvent.ACTION_UP:
updatePosition();
startX = startY = 0;
return true;
private void updatePosition(){
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.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;
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刷新的问题。一起来看下代码:
protected void onDraw(Canvas canvas) {
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);
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();
下载次数: 90
ithinkfeed
浏览: 68609 次
来自: 深圳
上向或者向下滑动时,最上一个item 或者最下一个item 总 ...
总结的关于添加和删除及判断是否存在快捷方式,Android应用 ...
老兄,请教一个问题,给应用程序创建快捷方式时,这个快捷方式的点 ...
2.2一下是不行的!!!
it's very good, 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
android activity开发文档翻译 - 1 - 基础篇
下载积分:30
内容提示:android activity开发文档翻译 - 1 - 基础篇
文档格式:PDF|
浏览次数:39|
上传日期: 03:23:49|
文档星级:
全文阅读已结束,如果下载本文需要使用
 30 积分
下载此文档
该用户还上传了这些文档
android activity开发文档翻译 - 1 - 基础篇
官方公共微信17:04 提问
Android 一个Activity悬浮在另一个Activity上
按赞数排序
把activity设置主题,为对话框,就可以了,再设置宽 高。
做过的给点思路或者给段代码 谢谢!!!
你确定这是两个activity而不是两个layout?
----------------------同志你好,我是CSDN问答机器人小N,奉组织之命为你提供参考答案,编程尚未成功,同志仍需努力!
将activity的样式theme修改为对话框的样式,
你可以去看看这个
其他相似问题把activity修改为悬浮窗口 - 开源中国社区
当前访客身份:游客 [
当前位置:
发布于 日 13时,
&无详细内容&
代码片段(1)
1.&[代码]先在values中定义xml样式,然后在配置文件中引用。&&&&
//配置文件
android:name="com.gao.food.dpclt.zxjc.lt_peopleInfo"
android:theme="@style/Theme.FloatActivity"
android:screenOrientation="portrait" /&
//样式文件
&!--activity 对话框样式
&style name="Theme.FloatActivity" parent="android:style/Theme.Dialog"&
&!-- float_box为我们定义的窗口背景--&
&item name="android:windowBackground"&@drawable/float_box&/item&
开源中国-程序员在线工具:
相关的代码(1524)
开源从代码分享开始
的其它代码

我要回帖

更多关于 android 悬浮窗半隐藏 的文章

 

随机推荐