Android创建悬浮窗的完整步骤

在Android中想要创建悬浮窗分为三步

1.申请权限

2.使用服务启动悬浮窗

3.设置悬浮窗参数并添加进WindowManager

下面话不多说了,来一起看看详细的实现过程

申请权限

首先需要申请悬浮窗权限,在清单文件中 manifest 下添加

<!-- 低版本悬浮窗所需权限 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

在Activity中动态申请权限

public class MainActivity extends Activity {
	/** 悬浮窗权限标识码 */
    public static final int CODE_WINDOW = 0;

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 申请悬浮窗权限
		if (Build.VERSION.SDK_INT >= 23) {
            if (!Settings.canDrawOverlays(this)) {
                Toast.makeText(this, "请打开此应用悬浮窗权限-Shendi", Toast.LENGTH_SHORT).show();
                startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), CODE_WINDOW);
            }
        }

        // 关闭当前activity,这样只显示悬浮窗
        finish();
    }

	// 权限申请成功后的回调
	@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        	// 不给权限就退出
            case Permission.CODE_WINDOW:
                if (resultCode != Activity.RESULT_OK) System.exit(0);
                break;
            default:
                Toast.makeText(this, "未知权限回调: " + requestCode, Toast.LENGTH_SHORT).show();
        }
    }
}

使用服务启动悬浮窗

对于悬浮窗的操作主要使用 WindowManager

创建一个服务,并在清单文件中注册

public class TestService extends Service {
	@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

在清单文件的Application中注册服务

<service android:name=".TestService" />

在Activity中启动服务

Intent intent = new Intent(this, TestService.class);
startService(intent);

接下来需要创建悬浮窗的界面,这里方便演示直接使用代码创建

也可以使用inflate函数将xml文件变view对象

View.inflate(context, R.layout.main_activity, null);

在服务的onStartCommand函数中内容如下

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
	Button btn = new Button(this);
	btn.setText("hello,world");

    return super.onStartCommand(intent, flags, startId);
}

设置悬浮窗参数并添加进WindowManager

这里直接上代码,看注释

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
	Button btn = new Button(this);
	btn.setText("hello,world");

	// 获取WindowManager
	WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
	// 创建布局参数
	WindowManager.LayoutParams params = new WindowManager.LayoutParams();
	/** 设置参数 */
	params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
	WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
                WindowManager.LayoutParams.TYPE_PHONE;
    params.format = PixelFormat.RGBA_8888;
    // 设置窗口的行为准则
    params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
    //设置透明度
    params.alpha = 1.0f;
    //设置内部视图对齐方式,这边位置为左边靠上
    params.gravity = Gravity.LEFT | Gravity.TOP;
    //窗口的左上角坐标
    params.x = 0;
    params.y = 0;
    //设置窗口的宽高,这里为自动
    params.width = WindowManager.LayoutParams.WRAP_CONTENT;
    params.height = WindowManager.LayoutParams.WRAP_CONTENT;

	// 添加进WindowManager
	wm.addView(btn, params);
    return super.onStartCommand(intent, flags, startId);
}

完整代码如下

TestActivity

package shendi.app.game.robot;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.Toast;

public class TestActivity extends Activity {

    /** 悬浮窗权限标识码 */
    public static final int CODE_WINDOW = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 申请悬浮窗权限
        if (Build.VERSION.SDK_INT >= 23) {
            if (!Settings.canDrawOverlays(this)) {
                Toast.makeText(this, "请打开此应用悬浮窗权限-Shendi", Toast.LENGTH_SHORT).show();
                startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), CODE_WINDOW);
            }
        }

        Intent intent = new Intent(this, TestService.class);
        startService(intent);

        // 关闭当前activity,这样只显示悬浮窗
        finish();
    }

    // 权限申请成功后的回调
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            // 不给权限就退出
            case Permission.CODE_WINDOW:
                if (resultCode != Activity.RESULT_OK) System.exit(0);
                break;
            default:
                Toast.makeText(this, "未知权限回调: " + requestCode, Toast.LENGTH_SHORT).show();
        }
    }

}

TestService

package shendi.app.game.robot;

import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.IBinder;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.Button;

public class TestService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Button btn = new Button(this);
        btn.setText("hello,world");

        // 获取WindowManager
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        // 创建布局参数
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        /** 设置参数 */
        params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY :
                WindowManager.LayoutParams.TYPE_PHONE;
        params.format = PixelFormat.RGBA_8888;
        // 设置窗口的行为准则
        params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        //设置透明度
        params.alpha = 1.0f;
        //设置内部视图对齐方式,这边位置为左边靠上
        params.gravity = Gravity.LEFT | Gravity.TOP;
        //窗口的左上角坐标
        params.x = 0;
        params.y = 0;
        //设置窗口的宽高,这里为自动
        params.width = WindowManager.LayoutParams.WRAP_CONTENT;
        params.height = WindowManager.LayoutParams.WRAP_CONTENT;

        // 添加进WindowManager
        wm.addView(btn, params);
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

运行 app,可以在屏幕左上角看到 hello,world的按钮悬浮

拖动效果

给悬浮组件添加触碰事件可以实现拖动效果,按钮组件不适用

这里给出简单的实现代码片段

private int upX, upY;
// 视图移动处理
view.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                upX = (int) event.getRawX();
                upY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                // 与上一次位置相差不到5则不移动
                if (event.getRawX() - upX > 5 || event.getRawY() - upY > 5) {
                    params.x = (int) event.getRawX();
                    params.y = (int) event.getRawY();
                    wm.updateViewLayout(view, params);
                }
                break;
            case MotionEvent.ACTION_UP:
                // 相差不到5则代表点击
                if (event.getRawX() - upX < 5 && event.getRawY() - upY < 5) {
                    // TODO
                }
                break;
        }
        return false;
    }
});

移除悬浮窗

可以在 onDestry 函数中进行移除

@Override
public void onDestroy() {
    wm.removeView(view);
    super.onDestroy();
}

总结

到此这篇关于Android创建悬浮窗的文章就介绍到这了,更多相关Android悬浮窗内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android 悬浮窗权限各机型各系统适配大全(总结)

    这篇博客主要介绍的是 Android 主流各种机型和各种版本的悬浮窗权限适配,但是由于碎片化的问题,所以在适配方面也无法做到完全的主流机型适配,这个需要大家的一起努力,这个博客的名字永远都是一个将来时. 悬浮窗适配 悬浮窗适配有两种方法:第一种是按照正规的流程,如果系统没有赋予 APP 弹出悬浮窗的权限,就先跳转到权限授权界面,等用户打开该权限之后,再去弹出悬浮窗,比如 QQ 等一些主流应用就是这么做得:第二种就是利用系统的漏洞,绕过权限的申请,简单粗暴,这种方法我不是特别建议,但是现在貌似有些

  • 不依赖于Activity的Android全局悬浮窗的实现

    前言 当我们在手机上使用360安全卫士时,手机屏幕上时刻都会出现一个小浮动窗口,点击该浮动窗口可跳转到安全卫士的操作界面,而且该浮动窗口不受其他activity的覆盖影响仍然可见(多米音乐也有相关的和主界面交互的悬浮小窗口).那么这种不受Activity界面影响的悬浮窗口是怎么实现的呢? Android悬浮窗实现 实现基础 Android悬浮窗实现使用WindowManager WindowManager介绍 通过Context.getSystemService(Context.WINDOW_S

  • android 添加随意拖动的桌面悬浮窗口

    用过新版本android 360手机助手都人都对 360中只在桌面显示一个小小悬浮窗口羡慕不已吧? 其实实现这种功能,主要有两步: 1.判断当前显示的是为桌面.这个内容我在前面的帖子里面已经有过介绍,如果还没看过的赶快稳步看一下哦. 2.使用windowManager往最顶层添加一个View .这个知识点就是为本文主要讲解的内容哦.在本文的讲解中,我们还会讲到下面的知识点: a.如果获取到状态栏的高度 b.悬浮窗口的拖动 c.悬浮窗口的点击事件 有开始之前,我们先来看一下效果图:  接下来我们来

  • Android悬浮窗屏蔽悬浮窗外部所有的点击事件的实例代码

    Android可以在所有应用上方添加View,就是给WindowManager添加一个View,在创建的View的时候可以给这个View设置LayoutParams(android.view.WindowManager.LayoutParams.LayoutParams())属性,默认是屏蔽View区域以外的所有点击事件,即在显示View的时候,屏幕的其它区域都不可点击,包括菜单和返回键等. 当给LayoutParams设置合适的flag后,其它区域就可以响应点击了. 示例代码: /** * 创

  • android编程实现悬浮窗体的方法

    本文实例讲述了android编程实现悬浮窗体的方法.分享给大家供大家参考,具体如下: 突然对悬浮窗体感兴趣,查资料做了个小Demo,效果是点击按钮后,关闭当前Activity,显示悬浮窗口,窗口可以拖动,双击后消失.效果图如下: 它的使用原理很简单,就是借用了WindowManager这个管理类来实现的. 1.首先在AndroidManifest.xml中添加使用权限: 复制代码 代码如下: <uses-permission android:name="android.permission

  • Android实现桌面悬浮窗、蒙板效果实例代码

    现在很多安全类的软件,比如360手机助手,百度手机助手等等,都有一个悬浮窗,可以飘浮在桌面上,方便用户使用一些常用的操作. 今天这篇文章,就是介绍如何实现桌面悬浮窗效果的. 首先,看一下效果图. 悬浮窗一共分为两个部分,一个是平常显示的小窗口,另外一个是点击小窗口显示出来的二级悬浮窗口. 首先,先看一下这个项目的目录结构. 最关键的就是红框内的四个类. 首先,FloatWindowService是一个后台的服务类,主要负责在后台不断的刷新桌面上的小悬浮窗口,否则会导致更换界面之后,悬浮窗口也会随

  • Android 8.0如何完美适配全局dialog悬浮窗弹出

    前言 最近项目targetSdkVersion升级到了26,出现很多问题趟了很多坑,其中就包括本篇的需要解决的问题:全局dialog 不显示. 出现场景 有时候我们需要在App中弹dialog,但是却不知道依附的是哪个Activity,这个时候通常会启动一个service来依附,显示一个全局的dialog. Android 6.0出现的悬浮窗权限 为什么从6.0说起? 在Android6.0之后,使用悬浮窗功能需要申请开启悬浮窗权限,在API23以下版本编译,悬浮窗权限关闭的,但是没有权限限制,

  • Android实现类似qq微信消息悬浮窗通知功能

    实现方法:(需要开启悬浮窗通知权限.允许应用在其他应用上显示) 一.利用headsup 悬挂式Notification,他是5.0中新增的,也就是API中的Headsup的Notification,可以在不打断用户操作的时候,给用户通知 二.使用Window创建悬浮窗 当window属性设置为FLAGE_NOT_FOCUSABLE表示不需要获取焦点,也不需要接受各种输入事件,此标记会同时启用FLAGE_NOT_TOUCH_MODEL,最终事件会直接传递给下层具有焦点的Widow FLAGE_NO

  • Android应用内悬浮窗的实现方案示例

    1.悬浮窗的基本介绍 悬浮窗,大家应该也不陌生,凌驾于应用之上的一个小弹窗,实现上很简单,就是添加一个系统级别的窗口,Android中通过WindowManagerService( WMS)来管理所有的窗口,对于WMS来说,管你是Activity.Toast.Dialog,都不过是通过WindowManagerGlobal.addView()添加的一个个View. Android中的窗口分为三个级别: 1.1 应用窗口,比如Activity的窗口; 1.2 子窗口,依赖于父窗口,比如PopupW

  • Android实现类似360,QQ管家那样的悬浮窗

    一.前言: 我手机从来不装这些东西,不过,有次看到同事的android手机上,有个QQ管家在桌面上浮着,同事拖动管家时,管家就变成一只鸟,桌面下方还有个弹弓,桌面顶部有只乌鸦,把管家也就是鸟拖动到弹弓那,然后,松手,鸟就飞出去.这个过程是动画过程,做的事,实际上是清楚内存. 二:原理: 其实,没什么原理,用到的就是WindowManager以及WindowManager.LayoutParams,对这个LayoutParams做文章,当设置为属性后,然后,创建一个View,将这个View添加到W

随机推荐