Android View绘制及事件(一)屏幕的视图层级,窗口概念初识
系列推荐:
Android View绘制及事件(二)setContentView()源码,LayoutInflater加载View的过程
Android View绘制及事件(三)自定义View及View绘制流程
Android View绘制及事件(四)自定义组合控件+约束布局ConstraintLayout+自定义控件属性
Android View绘制及事件(五)View响应事件及分发过程源码详解
目录
前言
通常情况下,我们创建一个Activity时,会通过setContentView来引入布局,将界面视图展现给用户看见。那么,为什么通过setContentView()就能将布局文件加载到界面中呢?PhoneWindow是什么呢?大家先来看一张屏幕层级的图:
- PhoneWindow: Window是一个抽象对象,它的具体实现类就是PhoneWindow。
- DecorView(FrameLayout):一个应用窗口的根布局容器。
- ContentView:窗口内容的容器, setContentView就是设置它的子View。
Window概念
public abstract class Window {
//设置布局文件
public abstract void setContentView(int layoutResID);
public abstract void setContentView(View view);
}
android.view.Window窗口抽象类。实际上,窗口是一个宏观的思想,在Android系统中,窗口是独占一个Surface实例的显示区域,每个窗口的Surface由WindowManagerService分配,当一块 Surface 显示在屏幕上时,就是用户所看到的窗口了。
WindowManagerService 添加一个窗口的过程,其实就是 WindowManagerService 为其分配一块 Surface 的过程,一块块的 Surface 在 WindowManagerService 的管理下有序的排列在屏幕上,Android 才得以呈现出多姿多彩的界面。(应用可以通过Canvas或OpenGL在其上面作画。画好之后,通过SurfaceFlinger将多块Surface按照Z-order的顺序进行混合,而后输出到FrameBuffer中,这样用户界面就得以显示。)
两个作用:
窗口主要用于 绘制各种UI元素 和 响应用户输入事件 。
三个类型:
分别是应用 Window、子 Window 和系统 Window。
- 应用类 Window 对应一个 Acitivity。
- 子 Window 不能单独存在,需要依附在特定的父 Window 中,比如常见的一些 Dialog。
- 系统 Window是需要声明权限才能创建的 Window,比如 Toast 和系统状态栏。
两个特点:
- 独立绘制,不与其它界面相互影响;
- 不会触发其它界面的输入事件;
三个核心组件:
- WindowManager.LayoutParams: 窗口的布局参数;
- Callback: 窗口的回调接口,通常由Activity实现;
- ViewTree: 窗口所承载的控件树。
PhoneWindow
PhoneWindow类继承于Window类,是Window类的具体实现,即我们可以通过该类具体去绘制窗口。并且,该类内部包含了 一个DecorView对象,该DectorView对象是所有应用窗口(Activity界面)的根View。
PhoneWindow的主要是把一个FrameLayout类即DecorView对象进行一定的包装,将它作为应用窗口的根View,并提供一组通用的窗口操作接口。另外,我们平时调用setContentView()方法设置Activity的用户界面时,实际上就完成了对所关联的PhoneWindow的ViewTree的设置
public class PhoneWindow extends Window implements MenuBuilder.Callback {
private DecorView mDecor; //该对象是所有应用窗口的根视图,是FrameLayout的子类
// 是DecorView的子布局mContentRoot中的子布局,也就是DecorView孙子节点
private ViewGroup mContentParent;
//设置标题
@Override
public void setTitle(CharSequence title) {
if (mTitleView != null) {
mTitleView.setText(title);
}
mTitle = title;
}
//设置背景图片
@Override
public final void setBackgroundDrawable(Drawable drawable) {
if (drawable != mBackgroundDrawable || mBackgroundResource != 0) {
mBackgroundResource = 0;
mBackgroundDrawable = drawable;
if (mDecor != null) {
mDecor.setWindowBackground(drawable);
}
}
}
//...
}
上一篇: mysql decimal_MySQL