Flags参数表示Window的属性,它有很多选项,通过这些选项可以控制Window的显示特性。
FLAG_NOT_FOCUSABLE: 表示Window不需要获取焦点,也不需要接收各种输入事件,此标记会同时启用FLAG_NOT_TOUCH_MODAL,最终事件会直接传递给下层的具有焦点的Window。
FLAG_NOT_TOUCH_MODAL: 在此模式下,系统会将当前Window区域以外的单击事件传递给底层的Window,当前Window区域以内的单击事件则自己处理。这个标记很重要,一般来说都需要开启此标记,否则其他Window将无法收到单击事件。
FLAG_SHOW_WHEN_LOCKED: 开启此模式可以让Window显示在锁屏的界面上。
Type参数表示Window的类型,Window有三种类型,分别是应用Window、子Window和系统Window。应用类Window对应着一个Activity。子Window不能单独存在,它需要附属在特定的父Window之中,比如常见的一些Dialog就是一个子Window。系统Window是需要声明权限才能创建的Window,比如Toast 和系统状态栏这些都是系统Window。Window是分层的,每个Window都有对应的z-ordered,层级大的会覆盖在层级小的Window的上面,这和HTML中的z-index的概念是完全一致的。在三类Window中,应用Window的层级范围是1-99,子Window的层级范围是1000-1999,系统Window的层级范围是2000-2999,这些层级范围对应着WindowManager.LayoutParams的type参数。如果想要Window位于所有Window的最顶层,那么采用较大的层级即可。很显然系统Window的层级是最大的,而且系统层级有很多值,一般我们可以选用TYPE_SYSTEM_OVERLAY或者TYPE_SYSTEM_ERROR,如果采用TYPE_SYSTEM_ERROR,只需要为type参数指定这个层级即可:
mLayoutParams.flags = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
同时声明权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
因为系统类型的Window是需要检查权限的,如果不在AndroidManifest中使用相应的权限,那么创建Window的时候就会报错。
Caused by: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@26079204 -- permission denied for this window type
WindowManager所提供的功能很简单,常用的只有三个功方法,即添加View、更新View和删除View,这三个方法定义在ViewManager中,而WindowManager继承了ViewManager
注意:MIUI系统需要在设置->其他应用管理->应用信息->权限管理,中打开“显示悬浮窗”才能显示。
示例代码:
package com.test.androidtest; import java.io.File; import java.io.FileFilter; import java.util.regex.Pattern; import android.support.v4.app.Fragment; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Vibrator; import android.util.DisplayMetrics; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.PixelFormat; import android.provider.Settings; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_main); //创建一个Window Button mFloatingButton = new Button(this); mFloatingButton.setText("悬浮按钮"); WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0, PixelFormat.TRANSPARENT); mLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; mLayoutParams.format = PixelFormat.RGBA_8888;//设置背景透明 mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; mLayoutParams.x = 500; mLayoutParams.y = 500; WindowManager mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE); mWindowManager.addView(mFloatingButton, mLayoutParams); } }
运行截图