Android开发者经常遇到应用想弹出悬浮窗的操作,而且有可能还想要高层级弹窗,就像ipone的浮标touch一样。android当然也有类似的悬浮图标,比如前些年我们的流量监控提醒。

这里我们忽略UI美学,简单记录一下:

1、基本使用

它的基本使用步骤是不会变的,只是有时候我们可能根据不同需求会改变它样式的参数,首先记得在 manifests.xml 清单文件中添加权限,然后根据需要申请权限,如果是系统级应用,可以让系统工程师配置赋予我们的应用权限:

    <!-- 允许程序添加悬浮窗 --><uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
if (!Settings.canDrawOverlays(this)) {Logger.d("onCreate: canDrawOverlays false.");Intent intent = new Intent();intent.setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);startActivity(intent);}else {Logger.d("onCreate: canDrawOverlays true.");showWindowView();}

具体的怎么添加呢:

    private void showWindowView(){//Activity中的方法,得到窗口管理器mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);//设置悬浮窗布局属性WindowManager.LayoutParams mWindowLayoutParams = new WindowManager.LayoutParams();//设置类型,具体有哪些值可取在后面附上// 设置窗体显示类型if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {mWindowLayoutParams.type =WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;} else {mWindowLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;}//设置行为选项,具体有哪些值可取在后面附上mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;//设置悬浮窗的显示位置mWindowLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
//        //设置悬浮窗的横竖屏,会影响屏幕方向,只要悬浮窗不消失,屏幕方向就会一直保持,可以强制屏幕横屏或竖屏
//        mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;//设置悬浮窗的宽度mWindowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;//设置悬浮窗的高度mWindowLayoutParams.height = 200;//设置悬浮窗的布局LinearLayout linearLayout = new LinearLayout(this);linearLayout.setBackgroundColor(Color.GRAY);TextView textView = new TextView(this);textView.setTextColor(getColor(R.color.white_16p));textView.setTextSize(32);textView.setGravity(Gravity.CENTER);textView.setText("测试浮窗");LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);linearLayout.addView(textView, layoutParams);//加载显示悬浮窗mWindowManager.addView(linearLayout, mWindowLayoutParams);}

注释中提到悬浮窗只要不消失,屏幕方向就会一直保持,如果设置悬浮窗横屏,将程序退到后台时,则手机桌面也会横屏,看起来就会很不舒服,所以如果不是特定需求,我们可以在 onStart() 的时候添加悬浮窗,然后在 onStop() 方法的时候调用 WindowManager 的 removeView() 方法让其消失,就不会影响屏幕方向了。需要注意的时候不能重复添加同一个悬浮窗,否则会报  java.lang.IllegalStateException: View android.widget.LinearLayout{3284dae1 V.E..... ......I. 0,0-0,0} has already been added to the window manager的异常,所以在添加悬浮窗之前最好先判断一下该悬浮窗是否已添加:

if (linearLayout.isAttachedToWindow())

2、type 和 flags 可取值

type 可取值

应用程序窗口。
public static final int FIRST_APPLICATION_WINDOW = 1;

所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。     
public static final int TYPE_BASE_APPLICATION =1;
    
普通应用功能程序窗口。token必须设置为Activity的token,以指出该窗口属谁。
public static final int TYPE_APPLICATION = 2;

用于应用程序启动时所显示的窗口。应用本身不要使用这种类型。
它用于让系统显示些信息,直到应用程序可以开启自己的窗口。   
public static final int TYPE_APPLICATION_STARTING = 3; 
     
应用程序窗口结束。
public static final int LAST_APPLICATION_WINDOW = 99;

子窗口。子窗口的Z序和坐标空间都依赖于他们的宿主窗口。
public static final int FIRST_SUB_WINDOW = 1000;

面板窗口,显示于宿主窗口上层。
public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;

媒体窗口,例如视频。显示于宿主窗口下层。
public static final int TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1;

应用程序窗口的子面板。显示于所有面板窗口的上层。(GUI的一般规律,越“子”越靠上)
public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW +2;

对话框。类似于面板窗口,绘制类似于顶层窗口,而不是宿主的子窗口。
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW +3;

媒体信息。显示在媒体层和程序窗口之间,需要实现透明(半透明)效果。(例如显示字幕)
public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW +4;

子窗口结束。( End of types of sub-windows )
public static final int LAST_SUB_WINDOW = 1999;

系统窗口。非应用程序创建。
public static final int FIRST_SYSTEM_WINDOW = 2000;

状态栏。只能有一个状态栏;它位于屏幕顶端,其他窗口都位于它下方。
public static final int TYPE_STATUS_BAR =  FIRST_SYSTEM_WINDOW;

搜索栏。只能有一个搜索栏;它位于屏幕上方。
public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;

电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;

系统提示。它总是出现在应用程序窗口之上。
public static final int TYPE_SYSTEM_ALERT =  FIRST_SYSTEM_WINDOW +3;

锁屏窗口。
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW +4;

信息窗口。用于显示toast。
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW +5;

系统顶层窗口。显示在其他一切内容之上。此窗口不能获得输入焦点,否则影响锁屏。
public static final int TYPE_SYSTEM_OVERLAY =  FIRST_SYSTEM_WINDOW +6;

电话优先,当锁屏时显示。此窗口不能获得输入焦点,否则影响锁屏。
public static final int TYPE_PRIORITY_PHONE =  FIRST_SYSTEM_WINDOW +7;

系统对话框。(例如音量调节框)。
public static final int TYPE_SYSTEM_DIALOG =  FIRST_SYSTEM_WINDOW +8;

锁屏时显示的对话框。
public static final int TYPE_KEYGUARD_DIALOG =  FIRST_SYSTEM_WINDOW +9;

系统内部错误提示,显示于所有内容之上。
public static final int TYPE_SYSTEM_ERROR =  FIRST_SYSTEM_WINDOW +10;

内部输入法窗口,显示于普通UI之上。应用程序可重新布局以免被此窗口覆盖。
public static final int TYPE_INPUT_METHOD =  FIRST_SYSTEM_WINDOW +11;

这个值我也不是每个都试过,所以具体效果会有什么不同不能妄言。感兴趣的可以都尝试一下。

flags 可取值

窗口之后的内容变暗。  
public static final int FLAG_DIM_BEHIND = 0x00000002; 
  
窗口之后的内容变模糊。  
public static final int FLAG_BLUR_BEHIND = 0x00000004;
  
不许获得焦点。不能获得按键输入焦点,所以不能向它发送按键或按钮事件。那些时间将发送给它后面的可以获得焦点的窗口。此选项还会设置FLAG_NOT_TOUCH_MODAL选项。设置此选项,意味着窗口不能与软输入法进行交互,所以它的Z序独立于任何活动的输入法(换句话说,它可以全屏显示,如果需要的话,可覆盖输入法窗口)。要修改这一行为,可参考FLAG_ALT_FOCUSALBE_IM选项。  
public static final int FLAG_NOT_FOCUSABLE = 0x00000008;
  
不接受触摸屏事件。  
public static final int FLAG_NOT_TOUCHABLE = 0x00000010;
  
当窗口可以获得焦点(没有设置 FLAG_NOT_FOCUSALBE 选项)时,仍然将窗口范围之外的点设备事件(鼠标、触摸屏)发送给后面的窗口处理。否则它将独占所有的点设备事件,而不管它们是不是发生在窗口范围内。  
public static final int FLAG_NOT_TOUCH_MODAL = 0x00000020;
  
如果设置了这个标志,当设备休眠时,点击触摸屏,设备将收到这个第一触摸事件。通常第一触摸事件被系统所消耗,用户不会看到他们点击屏幕有什么反应。  
public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
  
当此窗口为用户可见时,保持设备常开,并保持亮度不变。  
public static final int FLAG_KEEP_SCREEN_ON = 0x00000080;
  
窗口占满整个屏幕,忽略周围的装饰边框(例如状态栏)。此窗口需考虑到装饰边框的内容。  
public static final int FLAG_LAYOUT_IN_SCREEN =0x00000100;
  
允许窗口扩展到屏幕之外。  
public static final int FLAG_LAYOUT_NO_LIMITS =0x00000200;
  
窗口显示时,隐藏所有的屏幕装饰(例如状态条)。使窗口占用整个显示区域。  
public static final int FLAG_FULLSCREEN = 0x00000400;
  
此选项将覆盖FLAG_FULLSCREEN选项,并强制屏幕装饰(如状态条)弹出。  
public static final int FLAG_FORCE_NOT_FULLSCREEN =0x00000800;
  
抖动。指 对半透明的显示方法。又称“点透”。图形处理较差的设备往往用“点透”替代Alpha混合。  
public static final int FLAG_DITHER = 0x00001000;
 
不允许屏幕截图。  
public static final int FLAG_SECURE = 0x00002000;
  
一种特殊模式,布局参数用于指示显示比例。  
public static final int FLAG_SCALED = 0x00004000;
  
当屏幕有可能贴着脸时,这一选项可防止面颊对屏幕造成误操作。  
public static final int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000;
  
当请求布局时,你的窗口可能出现在状态栏的上面或下面,从而造成遮挡。当设置这一选项后,窗口管理器将确保窗口内容不会被装饰条(状态栏)盖住。  
public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000;
  
反转FLAG_NOT_FOCUSABLE选项。如果同时设置了FLAG_NOT_FOCUSABLE选项和本选项,窗口将能够与输入法交互,允许输入法窗口覆盖;如果FLAG_NOT_FOCUSABLE没有设置而设置了本选项,窗口不能与输入法交互,可以覆盖输入法窗口。  
public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000;
  
如果你设置了FLAG_NOT_TOUCH_MODAL,那么当触屏事件发生在窗口之外事,可以通过设置此标志接收到一个MotionEvent.ACTION_OUTSIDE事件。注意,你不会收到完整的down/move/up事件,只有第一次down事件时可以收到ACTION_OUTSIDE。  
public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;
  
当屏幕锁定时,窗口可以被看到。这使得应用程序窗口优先于锁屏界面。可配合FLAG_KEEP_SCREEN_ON选项点亮屏幕并直接显示在锁屏界面之前。可使用FLAG_DISMISS_KEYGUARD选项直接解除非加锁的锁屏状态。此选项只用于最顶层的全屏幕窗口。  
public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
  
请求系统墙纸显示在你的窗口后面。窗口必须是半透明的。  
public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
  
窗口一旦显示出来,系统将点亮屏幕,正如用户唤醒设备那样。  
public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
  
解除锁屏。只有锁屏界面不是加密的才能解锁。如果锁屏界面是加密的,那么用户解锁之后才能看到此窗口,除非设置了FLAG_SHOW_WHEN_LOCKED选项。  
public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
  
锁屏界面淡出时,继续运行它的动画。  
public static final int FLAG_KEEP_SURFACE_WHILE_ANIMATING =0x10000000;
  
以原始尺寸显示窗口。用于在兼容模式下运行程序。  
public static final int FLAG_COMPATIBLE_WINDOW = 0x20000000;
  
用于系统对话框。设置此选项的窗口将无条件获得焦点。  
public static final int FLAG_SYSTEM_ERROR = 0x40000000;

暂时记录一下吧,遇到的时候方便查一下。当然,这些实际上Android开发者官网源码里都能看到。

Android 应用弹出悬浮窗相关推荐

  1. html点击按钮弹出悬浮窗_9种实现点击一个链接弹出一个小窗口的代码

    9 种实现点击一个链接弹出一个小窗口的代码 因为着是一段 javascripts 代码, 所以它们应该放在之间. 是对一些版本低的浏览器起作用,在这些老浏览器中不会将 标签中的代码作为文本显示出来.要 ...

  2. html点击按钮弹出悬浮窗_JS控制弹出悬浮窗口(一览画面)的实例代码

    在web项目开发中经常遇到在一览画面中用户需要查看某一条记录的详细信息.如果用迁移画面的方式处理,速度会比较慢,而且用户体验不是太好.如果采用点击该条记录的详细链接时弹出一个层显示在当前画面的话,处理 ...

  3. html点击按钮弹出悬浮窗_javascript如何实现弹出浮动窗口

    Js弹出浮动窗口,支持鼠标拖动和关闭 /** 关于一些参数说明: *bodycontent:要在窗口显示的内容,dom对象 *title:窗口标题,字符串类型 *removeable:窗口能否拖动,布 ...

  4. html点击按钮弹出悬浮窗_网课助手1.0 支持悬浮窗搜题等多功能

    临近期末,又到了大学生期末网课考试测试的环节,以本人来看,这就是浪费时间,估计没有几个人真正的做题,基本就是百度题目.但是一个一个查题真的太麻烦了,最近在网上找的脚本基本都是电脑浏览器端的.没有手机端 ...

  5. html点击按钮弹出悬浮窗_点击文字或按钮弹出一个DIV窗口(DIV悬浮窗口)

    以下是弹出窗口代码: 点击文字弹出一个DIV层窗口代码 .black_overlay{ display: none; position: absolute; top: 0%; left: 0%; wi ...

  6. html点击按钮弹出悬浮窗_JS设置弹出小窗口。

    经常上网的朋友可能会到过这样一些网站,一进入首页立刻会弹出一个窗口,或者按一个连接或按钮弹出,通常在这个窗口里会显示一些注意事项.版权信息.警告.欢迎光顾之类的话或者作者想要特别提示的信息.其实制作这 ...

  7. Android 实现简单的悬浮窗按钮(一)

    先来看一下实现效果吧 功能较为简单,直接贴出主要实现代码: public class MainActivity extends AppCompatActivity implements View.On ...

  8. android浮标权限管理,Android辅助权限与悬浮窗

    Android辅助权限与悬浮窗在执行自动化服务的流程中,我们其实并不希望被用户的操作中断流程,所以有什么方法在用户点击自动化操作的过程中,避免用户再次操作呢?那就是开启一个全局透明的悬浮窗,进行屏蔽触 ...

  9. Android 查询及设置悬浮窗权限(AppOpsManager )

    需求确认: 最近产品在系统升级方面加了一个强制升级的需求,安装完成后需要通过dialog提示用户重启,如果当即拒绝,一个小时后继续弹出此dialog. 问题场景: 首先想到的是通过AlarManage ...

最新文章

  1. windows中路径\和 linux中用/
  2. python斗地主游戏源码_我用tkinter写的一个斗地主练习复盘python程序
  3. 个人作业收官——软件工程实践总结
  4. 线性代数导论5——SVD分解
  5. Django Tips
  6. 【LeetCode之C#解法】 移动零、爬楼梯
  7. Mynavi Programming Contest 2021(AtCoder Beginner Contest 201)题解
  8. 369寝室(数组、模拟)
  9. SolidWorks转3DMAX
  10. oracle计算时sum溢出_Oracle内存全面分析
  11. Python+OpenGL基本图元绘制综合演示
  12. linux内存管理(十二)-直接页面回收
  13. 关于在Android中访问和使用到上下文变量
  14. UIView的setNeedsLayout, layoutIfNeeded 和 layoutSubviews
  15. 让Xcode日志输出中文
  16. 双屏怎么快速切换鼠标_双屏触摸一体机功能特点解析
  17. 语音识别基本原理介绍之gmm-hmm续
  18. Java基础(四)线程快速了解
  19. 求最小公倍数的两种算法(最大公约数的三种算法)
  20. PHP ThinkPHP 命名空间引入(use )

热门文章

  1. 转帖 CSDN网友挑选的2007年最有价值文章-2010南非世界杯Vuvuzela
  2. php怎么写视频审核代码,媒体审核
  3. 京瓷4501i打印机扫描步骤_京瓷TASKalfa4501i说明书
  4. Hihocoder1690 AEIOU (动态规划)
  5. 爱客猴(echo)内容管理系统 v3.0
  6. 移动硬盘拷贝东西时快时慢的问题
  7. DM8分区表和分区索引管理
  8. 计算机26字母代码表,在英文中的26个字母里,每一个字母所对应的“0和1”所组成的代码是多少?...
  9. Android M Developer Preview - API Preview(一)
  10. 怎么才能学好CNC数控编程