Android好奇宝宝_05_PopupWindow与悬浮窗

这一篇讲讲PopupWindow与悬浮窗之间那些不得不说的故事。

之所以把PopupWindow与悬浮窗这两个放到一起讲,是因为这两个的实现原理基本是一致的,只是有点不同而已。

原理:

使用系统服务(WindowManagerService)将要显示的View添加进Window中。

WindowManagerService和ActivityManagerService是Android系统中两个最重要的服务,其中一个管理窗口显示,一个管理四大组件。

ActivityManagerService这里呢先不讲,以后再说。

简单讲下WindowManagerService,想深入了解的建议看下老罗大大的博客,新手慎入:传送门

以一个最简单的HelloWorld来说明:

当Activity被启动时,Activity会被分配一个Window,一个window代表一个充满屏幕的窗口。然后当我们调用setContentView时,我们要显示的View(后面用contentView表示)就会被添加进该Activity的window中。window接收到contentView后会根据设置在其外部包裹一些其它view(比如titlebar),然后请求WindowManagerService,WindowManagerService则向底层一层一层发送请求直到硬件将其显示出来。

上面的说明简化了很多过程,因为不是我想讲的重点,这一篇只是想简单讲下怎么用WindowManagerService,而不是它的实现原理(原理我也讲不来。。)。

一般我们添加View的方式是将子view添加到一个已经存在于window上的父view中。但其实利用WindowManagerService我们是可以直接将view添加的window中的,就像系统帮我们自动将setContentView的contentView添加到window一样。

两种方式的主要区别在于子view添加进父view,那么子view和父view就位于同一个window,但用WindowManagerService添加view,我们可以指定不同window(如果你有足够权限的话),我这里说的不同window是指他们的等级不同。PopupWindow依附于Activity,属于应用级。而悬浮窗就是属于系统级,所以它才可以保持在前端显示(其它系统级的window还有来电提醒,ANR、FC等系统警告等)。

再说说WindowManagerService和WindowManager的区别:

WindowManagerService是系统服务,当并不完全对开发者开放,而是使用WindowManager做为代理,提供部分功能和包装后的功能,可以说WindowManager是阉割版的WindowManagerService,那些会危害系统安全的功能被屏蔽了。Android系统中的系统服务基本都是这种方式。

说完原理来看看代码证实一下,先看下系统实现的PopupWindow,在根据原理来实现一个悬浮窗。

PopupWindow:

其实PopupWindow里面只有两句核心的代码,其它的都是一些位置和大小的计算。

(1)在构造方法中,通过传入的context或则view获得WindowManager:

        mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);

或者:

            mContext = contentView.getContext();
            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);

(2)通过WindowManager将PopupWindow添加进window:

mWindowManager.addView(mPopupView, p);

是不是炒鸡简单?

那么我们来开始实现悬浮窗:

(1)先获取WindowManager:

mWindowManager = (WindowManager) getApplication().getSystemService(Context.WINDOW_SERVICE);

注意这里要使用Application的context来获取WindowManager,如果使用activity.getSystemService(Context.WINDOW_SERVICE)来获取的话,得到的WindowManager的生命周期是小于等于Activity的,而使用上面这种方式得到的WindowManager是跟整个应用一样的,这样除非你的整个应用进程都被终结了,不然你的悬浮窗就可以一直显示。

(2)设置参数WindowManager.LayoutParams:

大小位置等可以根据需求来设置,但是要记住设置显示的级别:

wmParams.type = LayoutParams.TYPE_PHONE;

(3)将要显示的view添加进window:

mWindowManager.addView(floatView, wmParams);

当然你也可以对floatView和其子view进行点击、触摸等事件的监听,然后可以通过WindowManager的另一个方法来刷新floatView:

mWindowManager.updateViewLayout(floatView, wmParams);

举个栗子:

你可以监听触摸事件,得到触摸位置并设置进wmParams里,再调用updateViewLayout方法来实现悬浮窗随手指移动的效果。

一点补充:网上的悬浮窗demo很多都是在Service中生成的,其实在Activity生成是一样的。但Service的有个好处是可以让应用进程不那么容易被杀死。

楼主写的一个demo效果图:

这里的吃豆人是我再另一篇博文写得demo摘出来的,没啥好说的,有兴趣的可以去支持下:

一个有吃豆人删除动画的ListView

本篇Demo下载

终于摆脱每一篇都是讲AbsListView的厄运了。

求赞求评论

时间: 2024-11-02 06:43:45

Android好奇宝宝_05_PopupWindow与悬浮窗的相关文章

Android好奇宝宝_04_一个有3个功能的Adapter

感觉Android好奇宝宝这个系列是脱离不了ListView和GridView了... 这一篇呢来分享点好东西 一个自定义Adapter,可以快速实现三个功能: (1)自动缓存处理 好吧,这个功能不是我实现的.我只是照搬鸿洋大大的,我会简单说下,不过还是请先看下他的原文,再来看我添加的两个功能,传送门 (2)支持item的不同布局 提供一个接口来通过position和该position的数据来设置不同的布局 (3)局部刷新 只刷新指定item的某个子View,避免一直调用notifyDataSe

Android好奇宝宝_番外篇_看脸的世界_08

废话少说,先上效果图: (左侧的图片是我用window画图软件1分钟画的,所以就不要嫌丑了,You can you up no bb.) 这是我发过最挫的效果图了,不过这是由于没有图片素材导致的,就不要在意这些细节了,知道实现原理后完全可以发挥你的想象去实现更美观的效果. 这个效果也是有开源库的,不过我又把名字给忘了,不过我记得原理,于是就试着自己写了一下. 其实原理很简单,我在另一篇博客(一个有吃豆人删除动画的ListView)也说过了,这一篇当做兑换那些年少轻狂不更事时许下的诺言(是不是瞬间

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

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

Android好奇宝宝_番外篇_看脸的世界_05

上一篇番外篇讲了一个炒鸡炒鸡简单的自定义ProgressBar,这一篇基于上一篇的基础扩展为SeekBar,没看过上一篇的,请先看一遍:传送门 先上效果图(2G内存的机子运行模拟器,所以有点卡): 这个效果之前不知道在哪里看到过,我也忘了. 下面进入正题: 测量大小和绘制部分沿用上一篇ProgressBar的,不清楚的请走上面的传送门. 对比上一篇的扩展: (1)SeekBar能通过触摸改变刻度 (2)SeekBar上方添加一个显示当前刻度的浮动View(后面用FloatView表示) (1)通

android课程表控件、悬浮窗、Todo应用、MVP框架、Kotlin完整项目源码

Android精选源码 Android游戏2048 MVP Kotlin项目(RxJava+Rerotfit+OkHttp+Glide) Android基于自定义Span的富文本编辑器 android课程表控件效果源码 Dagger.Clean.MVP框架搭建,快速开发- Andorid 任意界面悬浮窗,实现悬浮窗如此简单 android模仿QQ登录后保存账号和密码效果源码 Android简洁清爽的Todo清单工具(MVP+okhttp3+retrofit+gson) Android优质博客 K

Android好奇宝宝_11_SwipeRefreshLayout原理浅析

上一篇文章写了一个RecyclerView的Demo,然后就想加个下拉刷新功能进去试试,由于RecyclerView算比较新的东西,所以暂时找不到什么开源库使用.于是想到了官方提供的SwipeRefreshLayout,号称能为任何View添加下拉刷新功能. SwipeRefreshLayout的使用很简单: (1)将要下拉刷新的View嵌套到SwipeRefreshLayout中: <jjj.demo.newstuffdemo.JJJSwipeRefreshLayout android:id=

Android好奇宝宝_番外篇_看脸的世界_03

无聊刷帖看到一个求助,试着写了一下. 一个自定义Switch控件,附带动画效果. 说是控件,其实是一个布局容器,先上效果图: 先讲原理,再看高清源码. 原理: 好像没啥原理,汗... 跟其它自定义容器控件一样,一般要注意: (1)计算好大小,宽度和高度 (2)计算好子View的布局位置 不是一般要注意的: (3)动画是用的nineoldandroids (4)遮挡效果是通过控制子View的绘制顺序 高清源码: (1)计算大小: protected void onMeasure(int width

Android好奇宝宝_06_聊一聊Android里的动画

这一篇我们来聊一聊高大上的动画效果. 首先说一个常识,一个对理解动画最重要的概念,亦是动画的本质: 动画的原理是利人眼的视觉暂留的特性,即如果一帧帧图像切换的足够快的话,人眼就察觉不到停顿,看起来就像连续的动画了. 动画的原理很简单,就是让图像进行快速的切换.动画的难点是计算出每两帧之间的差异,比如一个位移动画,对于每一帧你都必须计算出它的位置,如果是直线匀速的.很容易计算,但如果是曲线的而且还是有加速度(即移动的速度是会变化的)的,那么计算就会变的复杂了. 总结一下,动画有两个要素,一个是若干

Android好奇宝宝_07_ViewPager切换动画(兼容低版本)

闲着无聊,写写Demo 想着写一个图片轮播,百度了一下基本都是用ViewPager实现的,那就用ViewPager来练手. 写完了再自定义切换效果,发现3.0以下不兼容,只好想办法. 先上效果图: 下面一步一步来: (1)写布局: <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <jjj.demo.viewpager