前言

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

Android悬浮窗实现

实现基础

Android悬浮窗实现使用WindowManager

WindowManager介绍

通过Context.getSystemService(Context.WINDOW_SERVICE)可以获得 WindowManager对象。

每一个WindowManager对象都和一个特定的 Display绑定。

想要获取一个不同的display的WindowManager,可以用 createDisplayContext(Display)来获取那个display的 Context,之后再使用:Context.getSystemService(Context.WINDOW_SERVICE)来获取WindowManager。

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

调用的是WindowManager继承自基类的addView方法和removeView方法来显示和隐藏窗口。具体见后面的实例。

另:API 17推出了Presentation,它将自动获取display的Context和WindowManager,可以方便地在另一个display上显示窗口。

WindowManager实现悬浮窗需要声明权限

首先在manifest中添加如下权限:

注意:在MIUI上需要在设置中打开本应用的”显示悬浮窗”开关,并且重启应用,否则悬浮窗只能显示在本应用界面内,不能显示在手机桌面上。

服务获取和基本参数设置

[java] view plain copy print?在CODE上查看代码片派生到我的代码片

// 获取应用的Context

mContext = context.getApplicationContext();

// 获取WindowManager

mWindowManager = (WindowManager) mContext

.getSystemService(Context.WINDOW_SERVICE);

参数设置:

final WindowManager.LayoutParams params = new WindowManager.LayoutParams();

// 类型

params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

// WindowManager.LayoutParams.TYPE_SYSTEM_ALERT

// 设置flag

int flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;

// | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

// 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,弹出的View收不到Back键的事件

params.flags = flags;

// 不设置这个弹出框的透明遮罩显示为黑色

params.format = PixelFormat.TRANSLUCENT;

// FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口

// 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按

// 不设置这个flag的话,home页的划屏会有问题

params.width = LayoutParams.MATCH_PARENT;

params.height = LayoutParams.MATCH_PARENT;

params.gravity = Gravity.CENTER;

点击和按键事件

除了View中的各个控件的点击事件之外,弹窗View的消失控制需要一些处理。

点击弹窗外部可隐藏弹窗的效果,首先,悬浮窗是全屏的,只不过最外层的是透明或者半透明的:

具体实现

[java] view plain copy print?在CODE上查看代码片派生到我的代码片

package com.robert.floatingwindow;

import android.content.Context;

import android.graphics.PixelFormat;

import android.graphics.Rect;

import android.view.Gravity;

import android.view.KeyEvent;

import android.view.LayoutInflater;

import android.view.MotionEvent;

import android.view.View;

import android.view.View.OnKeyListener;

import android.view.View.OnTouchListener;

import android.view.WindowManager;

import android.view.View.OnClickListener;

import android.view.WindowManager.LayoutParams;

import android.widget.Button;

/**

* 弹窗辅助类

*

* @ClassName WindowUtils

*

*

*/

public class WindowUtils {

private static final String LOG_TAG = "WindowUtils";

private static View mView = null;

private static WindowManager mWindowManager = null;

private static Context mContext = null;

public static Boolean isShown = false;

/**

* 显示弹出框

*

* @param context

* @param view

*/

public static void showPopupWindow(final Context context) {

if (isShown) {

LogUtil.i(LOG_TAG, "return cause already shown");

return;

}

isShown = true;

LogUtil.i(LOG_TAG, "showPopupWindow");

// 获取应用的Context

mContext = context.getApplicationContext();

// 获取WindowManager

mWindowManager = (WindowManager) mContext

.getSystemService(Context.WINDOW_SERVICE);

mView = setUpView(context);

final WindowManager.LayoutParams params = new WindowManager.LayoutParams();

// 类型

params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

// WindowManager.LayoutParams.TYPE_SYSTEM_ALERT

// 设置flag

int flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;

// | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

// 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,弹出的View收不到Back键的事件

params.flags = flags;

// 不设置这个弹出框的透明遮罩显示为黑色

params.format = PixelFormat.TRANSLUCENT;

// FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口

// 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时,后面的应用图标由不可长按变为可长按

// 不设置这个flag的话,home页的划屏会有问题

params.width = LayoutParams.MATCH_PARENT;

params.height = LayoutParams.MATCH_PARENT;

params.gravity = Gravity.CENTER;

mWindowManager.addView(mView, params);

LogUtil.i(LOG_TAG, "add view");

}

/**

* 隐藏弹出框

*/

public static void hidePopupWindow() {

LogUtil.i(LOG_TAG, "hide " + isShown + ", " + mView);

if (isShown && null != mView) {

LogUtil.i(LOG_TAG, "hidePopupWindow");

mWindowManager.removeView(mView);

isShown = false;

}

}

private static View setUpView(final Context context) {

LogUtil.i(LOG_TAG, "setUp view");

View view = LayoutInflater.from(context).inflate(R.layout.popupwindow,

null);

Button positiveBtn = (Button) view.findViewById(R.id.positiveBtn);

positiveBtn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

LogUtil.i(LOG_TAG, "ok on click");

// 打开安装包

// 隐藏弹窗

WindowUtils.hidePopupWindow();

}

});

Button negativeBtn = (Button) view.findViewById(R.id.negativeBtn);

negativeBtn.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

LogUtil.i(LOG_TAG, "cancel on click");

WindowUtils.hidePopupWindow();

}

});

// 点击窗口外部区域可消除

// 这点的实现主要将悬浮窗设置为全屏大小,外层有个透明背景,中间一部分视为内容区域

// 所以点击内容区域外部视为点击悬浮窗外部

final View popupWindowView = view.findViewById(R.id.popup_window);// 非透明的内容区域

view.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

LogUtil.i(LOG_TAG, "onTouch");

int x = (int) event.getX();

int y = (int) event.getY();

Rect rect = new Rect();

popupWindowView.getGlobalVisibleRect(rect);

if (!rect.contains(x, y)) {

WindowUtils.hidePopupWindow();

}

LogUtil.i(LOG_TAG, "onTouch : " + x + ", " + y + ", rect: "

+ rect);

return false;

}

});

// 点击back键可消除

view.setOnKeyListener(new OnKeyListener() {

@Override

public boolean onKey(View v, int keyCode, KeyEvent event) {

switch (keyCode) {

case KeyEvent.KEYCODE_BACK:

WindowUtils.hidePopupWindow();

return true;

default:

return false;

}

}

});

return view;

}

}

总结

以上就是本文的全部内容,本文以实例形式较为详细的分析了Android悬浮窗口的原理与具体实现技巧,具有一定参考借鉴价值,希望给大家在开发Android应用中有所帮助。

Android实现顶层全局窗口,不依赖于Activity的Android全局悬浮窗的实现相关推荐

  1. Android开发笔记(一百一十八)自定义悬浮窗

    WindowManager 在前面< Android开发笔记(六十六)自定义对话框>中,我们提到每个页面都是一个Window窗口,许多的Window对象需要一个管家来打理,这个管家我们称之 ...

  2. Android窗口Window的创建(悬浮窗)

    创建悬浮窗以及基于无障碍服务的窗口 关于悬浮窗的创建 启动悬浮窗 关于前台服务 启动服务 无障碍窗口 知识点 参考链接 关于悬浮窗的创建 首先需要获取WindowManager WindowManag ...

  3. Android悬浮窗原理解析(Window)[源码]

    悬浮窗,在大多数应用中还是很少见的,目前我们接触到的悬浮窗,差不多都是一些系统级的应用软件,例如:360安全卫士,腾讯手机管家等:在某些服务行业如金融,餐饮等,也会在应用中添加悬浮窗,例如:美团的偷红 ...

  4. Android 悬浮窗基本使用

    很多 iPhone 用户都喜欢打开一项设置,那就是 AssistiveTouch ,我们俗称小白点,它位于整个屏幕之上,就像是漂浮在所有的 App 之上.Android 手机上也有很多应用有这样的东西 ...

  5. Android中自定义悬浮窗

    有时候,我们可能会需要制作一个始终悬浮的窗口显示一些关键信息.它独立于我们的页面,可以在不妨碍用户操作的情况下显示信息.这里我们就学习一下悬浮窗的做法. 1.WindowManager的常用方法 ge ...

  6. Android展开悬浮窗功能,Android 悬浮窗 (附圆形菜单悬浮窗)

    序言 Android悬浮窗的实现,主要有四个步骤: 1. 声明及申请权限 2. 构建悬浮窗需要的控件 3. 将控件添加到WindowManager 4. 必要时更新WindowManager的布局 一 ...

  7. android动态申请悬浮框权限,Android创建悬浮窗的完整步骤

    在Android中想要创建悬浮窗分为三步 1.申请权限 2.使用服务启动悬浮窗 3.设置悬浮窗参数并添加进WindowManager 下面话不多说了,来一起看看详细的实现过程 申请权限 首先需要申请悬 ...

  8. Android 悬浮窗

    悬浮窗是一种比较常见的需求.例如把视频通话界面缩小成一个悬浮窗,然后用户可以在其他界面上处理事情. 本文给出一个简单的悬浮窗实现.可缩小activity和还原大小.可悬浮在其他activity上.使用 ...

  9. android 微信浮窗实现_Android仿微信视屏悬浮窗效果

    在项目中需要对接入的腾讯云音视频,可以悬浮窗显示,悬浮窗可拖拽,并且在悬浮窗不影响其他的activity的焦点. 这个大神的文章Android基于腾讯云实时音视频仿微信视频通话最小化悬浮,他讲的是视频 ...

最新文章

  1. Sharding-Jdbc 实现读写分离 + 分库分表,写得太好了!
  2. 动态规划DP----背包问题总结
  3. Linux用户添加sudoer
  4. 【机器学习基础】(三):理解逻辑回归及二分类、多分类代码实践
  5. P1021 邮票面值设计
  6. [Swift]LeetCode1013. 将数组分成和相等的三个部分 | Partition Array Into Three Parts With Equal Sum...
  7. oracle启动监听读取哪个文件,监听服务启动及数据文件恢复oracle数据库
  8. python跟谁学_学 Python 都用来干嘛的?
  9. python实现删除文件与目录的方法
  10. 现代男人养生的10点忠告
  11. cenOS 安装opencv(for matlab)
  12. 线性回归、bagging回归、随机森林回归
  13. 哲理故事三百篇[转]
  14. 计算机键盘字母排列依据,键盘上的26个字母排序有什么规律吗?是怎么定的?...
  15. Linux中如何安装特定的gcc版本
  16. 如何让你的内网服务器可以被外网访问到(端口映射、NAT、域名解析、IP地址)
  17. 数云荣登乌镇互联网大会2016中国大数据创新企业50强
  18. 千千静听打开卡拉OK功能和弹窗广告过滤
  19. ffmpeg视频压缩命令
  20. 防止私自接交换机_【交换机】交换机如何配置防止用户手动私设IP

热门文章

  1. java 句柄池_深入理解JVM之Java对象的创建、内存布局、访问定位详解
  2. 能直接挂在iis的动静态网站_网站优化思路总结之前端
  3. 为什么使用HashMap需要重写hashcode和equals方法_为什么要重写hashcode和equals方法?你能说清楚了吗...
  4. 无软件linux,无需安装即可运行或演示Linux的方法 (1)
  5. BUUCTF(pwn) ciscn_2019_s_3 [ 栈溢出SROP攻击]
  6. flutter 判断字符创_Flutter 字符串与JSON相互转化
  7. Python中strip()、lstrip()、rstrip()用法详解
  8. 非常有用的15个Linux 服务器监控命令
  9. Python中的partial便函数的理解
  10. c语言程序的命令行输入,C程序获取命令行参数