其次、继续判断mContentParent对象是否为空,如果不为空,则调用generateLayout()方法去创建mContentParent对象。
generateLayout()方法如下:
protected ViewGroup generateLayout(DecorView decor) { // Apply data from current theme.
//...1、根据requestFreature()和Activity节点的android:theme=\设置好 features值
饰布局文件
int layoutResource; //窗口修饰布局文件 int features = getLocalFeatures();
// System.out.println(\ if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) { layoutResource com.android.internal.R.layout.dialog_title_icons;
} else {
layoutResource com.android.internal.R.layout.screen_title_icons;
}
// System.out.println(\
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0) {
// Special case for a window with only a progress bar (and title). // XXX Need to have a no-title version of embedded windows. layoutResource = com.android.internal.R.layout.screen_progress; // System.out.println(\ } //...
//3 选定了窗口修饰布局文件 ,添加至DecorView对象里,并且指
= =
//2 根据设定好的 features值,即特定风格属性,选择不同的窗口修
定mcontentParent值
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
ViewGroup
if (contentParent == null) {
throw new RuntimeException(\couldn't find content container view\
}
if
((features
&
(1
<<
FEATURE_INDETERMINATE_PROGRESS)) != 0) {
ProgressBar progress = getCircularProgressBar(false); if (progress != null) {
progress.setIndeterminate(true); } } //...
return contentParent; }
contentParent
=
(ViewGroup)findViewById(ID_ANDROID_CONTENT);
该方法会做如下事情:
1、根据窗口的风格修饰类型为该窗口选择不同的窗口布局文件(根视图)。这些窗口修饰布局文件指定一个用来存放Activity自定义布局文件的ViewGroup
视
图
,
一
般
为
FrameLayout
其
id
为
:
android:id=\。例如窗口修饰类型包括FullScreen(全屏)、NoTitleBar(不含标题栏)等。选定窗口修饰类型有两种:
①、指定requestFeature()指定窗口修饰符,PhoneWindow对象调用getLocalFeature()方法获取值;
②、为我们的Activity配置相应属性,即android:theme=“”,PhoneWindow对象调用getWindowStyle()方法获取值。
举
例
如
下
,
隐
藏
标
题
栏
有
如
下
方
法
:
requestWindowFeature(Window.FEATURE_NO_TITLE);或者 为Activity配置xml
属性:android:theme=”@android:style/Theme.NoTitleBar”。
PS:因此,在Activity中必须在setContentView之前调用requestFeature()方法。
确定好窗口风格之后,选定该风格对应的布局文件,这些布局文件位于 frameworks/base/core/res/layout/ ,典型的窗口布局文件有:
R.layout.dialog_titile_icons R.layout.screen_title_icons
R.layout.screen_progress R.layout.dialog_custom_title
R.layout.dialog_title
R.layout.screen_title // 最常用的Activity窗口修饰布局文件 R.layout.screen_simple //全屏的Activity窗口布局文件
上述这些布局文件都是以DecorView作为根视图,主要分为两个部分:显示标题栏的布局、显示Activity布局文件的布局(其id为content、被赋值给contentParent)
分析Activity最常用的一种窗口布局文件,R.layout.screen_title:
xmlns:android=\ android:orientation=\ android:fitsSystemWindows=\ android:layout_width=\ android:layout_height=\ style=\ android:layout_height=\ android:foregroundGravity=\ android:foreground=\
该布局文件很简单,一个LinearLayout下包含了两个子FrameLayout视图,第一个FrameLayout用来显示标题栏(TitleBar),该TextView 视图id为title(android:id=\;第二个FrameLayout用来显示我们Activity的
全屏的窗口布局文件 R.layout.screen_simple:
<--This is an optimized layout for a screen, with the minimum set of featuresenabled.-->
xmlns:android=\ android:id=\ android:fitsSystemWindows=\ android:foregroundInsidePadding=\ android:foregroundGravity=\ android:foreground=\该布局文件只有一个FrameLayout,用来显示我们Activity的布局文件,该FrameLayoutid为 android:id=\ 2、前面一步我们确定窗口修饰布局文件后,mDecor做为根视图将该窗口布局对应的视图添加进去,并且获取id为content的View,将其赋值给mContentParent对象,即我们前面中提到的第二个FrameLayout。 At Last、产生了mDecor和mContentParent对象后,就将我们的Activity布局文件直接添加至mContentParent父视图中即可。我们再次回到 Step 2 中PhoneWindow.setContentView() 该方法在PhoneWindow类中: 布 局 文 件 的 父 视 图 , 该 FrameLayoutid 为 content(android:id=\。 @Override public void setContentView(int layoutResID) { if (mContentParent == null) { installDecor(); } else { mContentParent.removeAllViews(); } mLayoutInflater.inflate(layoutResID, mContentParent); final Callback cb = getCallback(); if (cb != null) { cb.onContentChanged(); } } 整个过程主要是如何把Activity的布局文件添加至窗口里,上面的过程可以概括为: 1、创建一个DecorView对象,该对象将作为整个应用窗口的根视图 2、创建不同的窗口修饰布局文件,并且获取Activity的布局文件该存放的地方,由该窗口修饰布局文件内id为content的FrameLayout指定 。 3、将Activity的布局文件添加至id为content的FrameLayout内。 最后,当AMS(ActivityManagerService)准备resume一个Activity时,会回调该Activity的handleResumeActivity()方法,该方法会调用Activity的makeVisible方法 ,显示我们刚才创建的mDecor 视图族。 //系统resume一个Activity时,调用此方法 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) { ActivityRecord r = performResumeActivity(token, clearHide); //... if (r.activity.mVisibleFromClient) { r.activity.makeVisible(); } } makeVisible()方法原型如下: 位于ActivityThread类中: void makeVisible() { if (!mWindowAdded) {