Window和WindowManager

  • Window表示一个窗口的概念,在日常开发中直接接触Window的机会并不多,但是在某些特殊时候我们需要在桌面上显示一个类似悬浮窗的东西,那么这种效果就需要用到Window来实现。Window是一个抽象类,它的具体实现是PhoneWindow。创建一个Window是很简单的事,只需要通过WindowManager即可完成。WindowManager是外界访问Window的入口,Window的具体实现位于WindowManagerService中,WindowManager和Window-ManagerService的交互是一个IPC过程。Android中所有的视图都是通过Window来呈现的,不管是Activity、Dialog还是Toast,它们的视图实际上都是附加在Window上的,因此Window实际是View的直接管理者。从第4章中所讲述的View的事件分发机制也可以知道,单击事件由Window传递给DecorView,然后再由DecorView传递给我们的View,就连Activity的设置视图的方法setContentView在底层也是通过Window来完成的。
  • 下面代码是在window 400*400的位置上添加一个button,即使跳转Activity也依然再顶部展示按钮
val button = Button(this)
        button.text = "button"
        val layoutParams = WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT
                , WindowManager.LayoutParams.WRAP_CONTENT
                , WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY
                , 0
                , PixelFormat.TRANSPARENT)
        layoutParams.flags = (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)
        layoutParams.gravity = Gravity.LEFT or Gravity.TOP
        layoutParams.x = 400
        layoutParams.y = 400
        val windowManager = windowManager
        windowManager.addView(button, layoutParams)
  • WindowManager. LayoutParams中的flagstype这两个参数比较重要
    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.type = LayoutParams.TYPE_SYSTEM_ERROR;同时声明权限:uses-permissionandroid:name=“android.permission.SYSTEM_ALERT_WINDOW”/。因为系统类型的Window是需要检查权限的,如果不在AndroidManifest中使用相应的权限,那么创建Window的时候就会报错
  • WindowManager所提供的功能很简单,常用的只有三个方法,即添加View、更新View和删除View,这三个方法定义在ViewManager中,而WindowManager继承了ViewManager。
public void addView(View view,ViewGroup.LayoutParams params);
public void updateViewLayout(View view,ViewGroup.LayoutParams params);
public void removeView(View view);
  • WindowManager常用的就只有这三个功能而已,但是这三个功能已经足够我们使用了。它可以创建一个Window并向其添加View,还可以更新Window中的View,另外如果想要删除一个Window,那么只需要删除它里面的View即可。由此来看,WindowManager操作Window的过程更像是在操作Window中的View。我们时常见到那种可以拖动的Window效果,其实是很好实现的,只需要根据手指的位置来设定LayoutParams中的x和y的值即可改变Window的位置。
public boolean onTouch(View v,MotionEvent event) {
	int rawX = (int) event.getRawX();
	int rawY = (int) event.getRawY();
	switch (event.getAction()) {
		case MotionEvent.ACTION_MOVE: {
			mLayoutParams.x = rawX;
			mLayoutParams.y = rawY;
			mWindowManager.updateViewLayout(mFloatingButton,mLayoutParams);
			break;
		}
		default:
			break;
		}
		return false;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值