Android 开发艺术探索笔记之八 -- 理解 Window 和 WindowManager

写在最前:本文涉及到源码的部分,查看的是 Android 8.1.0_r33 的源码,部分与原文中代码有出入。

附上查看源码的网址:http://androidxref.com/


学习内容:

  • Window 和 WindowManager
  • Window 的内部工作原理
    • Window 的添加、更新和删除
  • Actvitiy、Dialog 等类型的 Window 对象的创建过程

原文开篇部分:

  • Window 是一个抽象类,具体实现是 PhoneWindow
  • WindowManager 是外界访问 Window 的入口,Window 的实现位于 WindowManagerService 中,WindowManager 和 WindowManagerService 的交互是一个 IPC 过程
  • Window 实际是 View 的管理者,视图都是通过 Window 呈现的。

1.Window 和 WindowManger

通过 WindowManager 添加一个 Window

mFloatingButton = new Button(this);
mFloatintButton.setText("button");

mLayoutParams = new WindowManager.LayoutParams(LayoutParams.RTAP_CONTENT,LayoutParams.WRAP_CONTENT,0,0,PixelFormat.TRANSPARENT);
mLayoutParams.flags = KatiytOarams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_SHOW_WHEN_LOCKED;
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.x = 100;
mLayoutParams.y = 300;

mWindowManager.addView(mFloatingButton, mLayoutParams);

通过以上代码,可以将一个 Button 添加到坐标为(100,300)的位置上。

下面说明 WindowManager.LayoutParams 中的 flagstype 这两个参数:

  1. flags 参数表示 Window 的属性,下面列出一个常用的选项:

    1. FLAG_NOT_FOCUSABLE
      表示 WIndow 不需要获取焦点,也不需要接收各种输入事件,最终事件会传递给下层的具有焦点的 Window

    2. FLAG_NOT_TOUCH_MODAL
      系统会将当前 Window 区域以外的单击事件传递给底层的 Window,当前 Window 区域以内的事件则自己处理。一般开启,否则其他 Window 将无法收到单击事件

    3. FLAG_SHOW_WHEN_LOCKED
      开启此模式可以让 Window 显示在锁屏界面

  2. Type 参数表示 Window 的类型,Window 有三种类型:

    1. 应用 Window:对应一个 Activity;层级范围是 1 ~ 99。
    2. 子 Window:不能单独存在,需要附属再特定的父 Window 上,比如常见的 Dialog;层级范围是 1000 ~ 1999
    3. 系统 Window:需要声明权限才能创建的 Window,比如 Toast;层级范围是 2000 ~ 2999

    关于上面提到的层级范围,此处进行说明:Window 是分层的,每个 Window 都有对应的 z-ordered,层级大的会覆盖再层级小的 Window 的上面。

WindowManager 提供的功能

提供的功能很简单,一般只有三个方法:添加 View、更新 View 和删除 View,这三个方法定义在接口 ViewManager 中(WindowManager 继承了 ViewManager)

public interface ViewManager
{
   
    public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

//继承关系
public interface WindowManager extends ViewManager {
   
    //...
}

原文中说道,”WindowManager 操作 Window 的过程更像是在操作 Window 中的 View“。


2. Window 的内部机制

Window 是一个抽象概念,每一个 Window都对应着一个 View 和一个 ViewRootImpl,WIndow 和 View 通过 ViewRootImpl 建立联系,因此 Window 以 View 的形式存在,View 才是 Window 存在的实体

实际开发中,对 Window 的访问必须通过 WindowManager。

2.1 Window 的添加过程

添加过程通过 WindowManager 的 addView 来实现,具体实现类是 WindowManagerImpl 类。

    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

    @Override
    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.updateViewLayout(view, params);
    }
    @Override
    public void removeView(View view) {
        mGlobal.removeView(view, false);
    }

可以看到,实际上 WindowManagerImp 采用了桥接模式,将具体的实现 委托 给了 mGlobal(WindowManagerGlobal)来处理,WindowManagerGlobal 以工厂的形式向外提供自己的实例。

WindowManagerGlobal 的 addView 方法有如下几步:

  1. 检查参数是否合法,如果是子 Window 那么还需要调整一些布局参数

    if (view == 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值