由于众所周知的原因,Android系统虽然提供了悬浮窗的功能,但使用之前需要用记授权,有些手机对这个授权还要再次确认,以至于很多用户出于谨慎的目地就不去打开了。但我们在实际开发当中却又需要这个功能是该怎么? 既然直接使用是不行了,那只能考虑折中的办法了。首先能想到的是把悬浮窗作在XML布局里面,不用时隐藏,需要时显示。但如果我们遇到一批需要悬浮窗的界面时要怎么办?有一个比较稳妥的方法;从DecorView下手! 我们知道Activity对于界面的加载是交给自己的手下PhoneWindow去处理的,PhoneWindow再交给自己的手下DecorView。DecorView虽然是一个FrameLayout的自定义类,理论上由它来加载就可以了,但DecorView还挺能整活,它不直接加载我们定义的XML布局,而是先加载了一个系统内置的布局,这个内置的布局是LinearLayout结构的,上面是一个标题区,下面是内容区,内容区就是一个FrameLayout,并且有一个系统级的ID作为标记。这个内置布局结构如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical"> <ViewStub android:id="@+id/action_mode_bar_stub" android:inflatedId="@+id/action_mode_bar" android:layout="@layout/action_mode_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="?attr/actionBarTheme" /> <FrameLayout android:id="@android:id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:foregroundInsidePadding="false" android:foregroundGravity="fill_horizontal|top" android:foreground="?android:attr/windowContentOverlay" />LinearLayout>
我们自定义的XML布局就是被加载到这个ID为content的FrameLayout里的。由于这是一个系统内置的布局,每一个Activity都有,所以我们可以充分利用这一便利来给实现我们的悬浮窗效果。
大致的思路是这样的:
自定义一个Activity子类专门用于处理悬浮窗的操作,在项目中需要用到悬浮窗的地方就继承这个类。
在自定义的Activity子类中通过findViewById(android.R.id.content)获取到系统内置的内容布局(ContentFrameLayout)。
自定义一个View作为我们的悬浮窗,然后将这个View添加到内容布局。
下面就来实例个带拖动效果的悬浮窗
悬浮窗带拖动效果
先自定义一个FloatActivity,封装一下悬浮窗的功能。由于我们的悬浮窗是带有拖动功能的,所以还需要把窗体的坐标保存在配置文件里,以便于Activity在跳转的时