DecorView是顶级View,一般情况下它内部会包含一个竖直方向的LinearLayout,在这个LinearLayout里面有上下2部分,上面是标题栏,下面是内容栏。在Activity中我们通过setContentView所设置的布局文件其实就是被加载到内容栏之中。
本文,将介绍DecorView是如何创建与显示的。
说明:本文若无特殊说明,源码分析对应为api21。
一.DecorView的创建
上面我们提到,DecorView是显示的顶层View,那么View的绘制准备从DecorView开始说起。而DecorView的开始 就是我们熟悉的 setContentView()。
//代码片1 (Activity类)
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
查看后发现,getWindow()返回的是Window类。而我们知道,Window是抽象类,而PhoneWindow是它的唯一实现类。也就是说,想了解 getWindow().setContentView(layoutResID) ,其实是PhoneWindow类的setContentView 方法。
//代码片2(PhoneWindow类)
@Override
public void setContentView(int layoutResID) {
// 1. 若mContentParent为空,创建一个DecroView
// mContentParent即为内容栏(content)对应的DecorView = FrameLayout子类
if (mContentParent == null) {
installDecor(); ---->分析1
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
// 若不为空,则删除其中的View
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
// 2. 为mContentParent添加子View
// 即Activity中设置的布局文件
mLayoutInflater.inflate(layoutResID, mContentParent);
}
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
我们来看一下代码片2中的分析1部分(即第7行代码):
//代码片3(PhoneWindow类)
private void installDecor() {
if (mDecor == null) {
//1. 通过赋值可以发现,mDecor就是DecorView。
// (DecorView的描述)This is the top-level view of the window, containing the window decor.
// private DecorView mDecor;