(转载)简易的可拖动的桌面悬浮窗效果

本文转载自:http://www.cnblogs.com/xqxacm/p/4918470.html

首先,我们需要知道,悬浮窗分为两种:Activity级别的悬浮窗,系统级别的悬浮窗

Activity级别的悬浮窗跟随所属Activity的生命周期而变化,而系统级别的悬浮窗则可以脱离Activity而存在。

由此可知,要实现360手机卫士那样的悬浮窗效果,就需要使用系统级别的悬浮窗

下面学习实现桌面悬浮窗效果的代码步骤:

1、配置清单文件AndroidManifest.xml 中 添加系统悬浮窗的权限

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

2、开始Activity代码的编写

先看成员变量:

    private WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
    private static WindowManager windowManager;
    private static ImageView imageView;

onCreate()方法:

获取WindwoManager对象,该对象是系统级别的

windowManager = (WindowManager) getApplication().getSystemService(WINDOW_SERVICE);

使用WindowManager可以显示在其他应用最上层,甚至手机桌面最上层显示窗口。

3、添加一个UI空间,作为悬浮窗的内容 ,当然Demo是一个ImageView作为悬浮窗内容,实际项目中就需要用复杂View,ViewGroup来扩展功能    

     //注意,悬浮窗只有一个,而当打开应用的时候才会产生悬浮窗,所以要判断悬浮窗是否已经存在,     if (imageView != null){
            windowManager.removeView(imageView);
        }
        // 使用Application context 创建UI控件,避免Activity销毁导致上下文出现问题,因为现在的悬浮窗是系统级别的,不依赖与Activity存在
           imageView = new ImageView(getApplicationContext());
        imageView.setImageResource(R.mipmap.normal);

4、设置系统级别的悬浮窗的参数,保证悬浮窗悬在手机桌面上

     lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
                  |WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;

        lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                  |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
//TYPE_SYSTEM_ALERT  系统提示,它总是出现在应用程序窗口之上
//TYPE_SYSTEM_OVERLAY   系统顶层窗口。显示在其他一切内容之上。此窗口不能获得输入焦点,否则影响锁屏
// FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按,不设置这个flag的话,home页的划屏会有问题
// FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口

关于 WindowManager.LayoutParams 的详解 请参考:Android中WindowManager.LayoutParams类详解
5、悬浮窗默认显示的位置
 lp.gravity = Gravity.LEFT|Gravity.TOP;  //显示在屏幕左上角

6、悬浮窗相对5默认位置的位置差和悬浮窗宽高设置

     //显示位置与指定位置的相对位置差
        lp.x = 0;
        lp.y = 0;
        //悬浮窗的宽高
        lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;

7、设置悬浮窗背景透明

lp.format = PixelFormat.TRANSPARENT;

8、将悬浮窗添加到WindowManager对象中

 windowManager.addView(imageView,lp);

9.设置悬浮窗的响应事件

这里为移动悬浮窗操作,可以自己扩展添加点击等响应事件

imageView.setOnTouchListener(new View.OnTouchListener() {
            private float lastX; //上一次位置的X.Y坐标
            private float lastY;
            private float nowX;  //当前移动位置的X.Y坐标
            private float nowY;
            private float tranX; //悬浮窗移动位置的相对值
            private float tranY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                boolean ret = false;
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        // 获取按下时的X,Y坐标
                        lastX = event.getRawX();
                        lastY = event.getRawY();
                        ret = true;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        // 获取移动时的X,Y坐标
                        nowX = event.getRawX();
                        nowY = event.getRawY();
                        // 计算XY坐标偏移量
                        tranX = nowX - lastX;
                        tranY = nowY - lastY;
                        // 移动悬浮窗
                        lp.x += tranX;
                        lp.y += tranY;
                        //更新悬浮窗位置
                        windowManager.updateViewLayout(imageView,lp);
                        //记录当前坐标作为下一次计算的上一次移动的位置坐标
                        lastX = nowX;
                        lastY = nowY;
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                }
                return ret;
            }
        });

10、效果图:

完整代码:注意添加权限!!
package com.xqx.window.app;

import android.app.Activity;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.*;
import android.widget.ImageView;

/**
 * 系统级别悬浮窗,可以在手机桌面上显示的悬浮窗
 */
public class FloatWindowActivity extends Activity {

    private WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
    private static WindowManager windowManager;
    private static ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_float_window);

        // 1、获取系统级别的WindowManager
        windowManager = (WindowManager) getApplication().getSystemService(WINDOW_SERVICE);

        // 判断UI控件是否存在,存在则移除,确保开启任意次应用都只有一个悬浮窗
        if (imageView != null){
            windowManager.removeView(imageView);
        }
        // 2、使用Application context 创建UI控件,避免Activity销毁导致上下文出现问题
        imageView = new ImageView(getApplicationContext());
        imageView.setImageResource(R.mipmap.normal);

        // 3、设置系统级别的悬浮窗的参数,保证悬浮窗悬在手机桌面上
        // 系统级别需要指定type 属性
        // TYPE_SYSTEM_ALERT 允许接收事件
        // TYPE_SYSTEM_OVERLAY 悬浮在系统上
        // 注意清单文件添加权限

        //系统提示。它总是出现在应用程序窗口之上。
        lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
                  |WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;

        // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口
        // FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按,不设置这个flag的话,home页的划屏会有问题
        lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                  |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

        //悬浮窗默认显示的位置
        lp.gravity = Gravity.LEFT|Gravity.TOP;
        //显示位置与指定位置的相对位置差
        lp.x = 0;
        lp.y = 0;
        //悬浮窗的宽高
        lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;

        lp.format = PixelFormat.TRANSPARENT;
        windowManager.addView(imageView,lp);

        //设置悬浮窗监听事件
        imageView.setOnTouchListener(new View.OnTouchListener() {
            private float lastX; //上一次位置的X.Y坐标
            private float lastY;
            private float nowX;  //当前移动位置的X.Y坐标
            private float nowY;
            private float tranX; //悬浮窗移动位置的相对值
            private float tranY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                boolean ret = false;
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        // 获取按下时的X,Y坐标
                        lastX = event.getRawX();
                        lastY = event.getRawY();
                        ret = true;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        // 获取移动时的X,Y坐标
                        nowX = event.getRawX();
                        nowY = event.getRawY();
                        // 计算XY坐标偏移量
                        tranX = nowX - lastX;
                        tranY = nowY - lastY;
                        // 移动悬浮窗
                        lp.x += tranX;
                        lp.y += tranY;
                        //更新悬浮窗位置
                        windowManager.updateViewLayout(imageView,lp);
                        //记录当前坐标作为下一次计算的上一次移动的位置坐标
                        lastX = nowX;
                        lastY = nowY;
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                }
                return ret;
            }
        });
    }

}

 
时间: 2024-12-26 07:57:03

(转载)简易的可拖动的桌面悬浮窗效果的相关文章

Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/8689140 大家好,今天给大家带来一个仿360手机卫士悬浮窗效果的教程,在开始之前请允许我说几句不相干的废话. 不知不觉我发现自己接触Android已有近三个年头了,期间各种的成长少不了各位高手的帮助,总是有很多高手喜欢把自己的经验写在网上,供大家来学习,我也是从中受惠了很多,在此我深表感谢.可是我发现我却从来没有将自己平时的一些心得拿出来与大家分享,共同学习,太没有奉献精神了.

Android开发之仿手机卫士悬浮窗效果

基本的实现原理,这种桌面悬浮窗的效果很类似与Widget,但是它比Widget要灵活的多.主要是通过WindowManager这个类来实现的,调用这个类的addView方法用于添加一个悬浮窗,updateViewLayout方法用于更新悬浮窗的参数,removeView用于移除悬浮窗.其中悬浮窗的参数这里有必要详细说明一下. WindowManager.LayoutParams这个类用于提供悬浮窗所需的参数,其中有几个经常会用到的变量: type值用于确定悬浮窗的类型,一般设为2002,表示在所

Android仿360手机卫士悬浮窗效果

请看下图:                         首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速.好,我们现在就来模拟实现一下类似的效果. 先谈一下基本的实现原理,这种桌面悬浮窗的效果很类似与Widget,但是它比Widget要灵活的多.主要是通过WindowManager这个类来实现的,调用这个类的addView方法用于添加一个悬浮窗,updateViewLayout方法用于更新悬浮窗的参数,removeView用于移除

android桌面悬浮窗实现

                        首先是一个小的悬浮窗显示的是当前使用了百分之多少的内存,点击一下小悬浮窗,就会弹出一个大的悬浮窗,可以一键加速.好,我们现在就来模拟实现一下类似的效果. 1.新建一个项目 , 打开activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.an

android桌面悬浮窗仿QQ手机管家加速效果

主要还是用到了WindowManager对桌面悬浮进行管理. 需要一个火箭的悬浮窗 一个发射台悬浮窗  ,判断火箭是否放到了发射台,如果放上了,则使用AsyTask 慢慢将火箭的图片往上移.结束后., 返回原位. 1.打开activity_main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.andro

Android桌面悬浮窗

经常,我们看到在桌面上可移动的悬浮窗,这种场景还是很多的, 像流量统计,桌面歌词等,安全软件的清理小部件 这种小部件主要是通过 WindowManager ; WindowManager.LayoutParams 这两个类来实现 调用 WindowManager 的addView(view, params)方法来添加一个悬浮窗.updateViewLayout(view,params)来更新悬浮窗参数.removeView(view)用于移除悬浮窗 WindowManager.LayoutPar

可拖动缩放视频悬浮窗

直接上图      可进行三级缩放和拖动的视频悬浮窗口 一.悬浮窗口 1.1.创建WindowManager //创建params,控制大小位置 mParams = WindowManager.LayoutParams() //悬浮窗口 mWindowManager = application.getSystemService(Context.WINDOW_SERVICE) as WindowManager //权限要求 mParams.type = if (Build.VERSION.SDK_

Android WindowManager实现悬浮窗效果 (一)——与当前Activity绑定

最近有学生做毕业设计,想使用悬浮窗这种效果,其实很简单,我们可以通过系统服务WindowManager来实现此功能,本章我们来试验一下在当前Activity之上创建一个悬浮的view. 第一步:认识WindowManager l  这个接口用于与 window manager (窗口管理器, 应用框架层) 进行交互. l  通过getSystemService(Context.WINDOW_SERVICE)可以获取到WM的实例. l  继承关系 public interface WindowMa

C# WPF QQ新消息托盘悬浮窗效果实现

今天在做一个项目的时候需要这么一个效果,但是网上找了一会发现并没有现成的给我参考(复制),但是呢,我千(到)辛(处)万(抄)苦(袭)想(复)破(制)头(粘)脑(贴)终于还是给做出来了~嘿嘿嘿 QQ新消息悬浮窗即:QQ有新消息时托盘图标会闪动,此时移动鼠标到托盘图标上就会显示一个弹框了,那么呢我把这个弹框称为“QQ新消息托盘悬浮窗”.当鼠标从托盘图标移走后弹框隐藏,我们要做的效果就是这样的. 项目效果图: 涉及到的内容主要有:Popup,win32api,DispatcherTimer(定时器).