protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
public DecorView(Context context, int featureId) {
super(context);
mFeatureId = featureId;
}
很遗憾,我们的generateDecor()只是初始化了一个FrameLayout对象,并没有在其内部压入布局文件,看来我们的猜测有些问题;不过没事,既然此方法没有,那么generateLayout(mDecor);中一定设置了layout文件,并且这名字也很像这么回事。
5、PhoneWindow generateLayout
=============================
protected ViewGroup generateLayout(DecorView decor) {
// Apply data from current theme.
TypedArray a = getWindowStyle();
//...Window_windowIsFloating,Window_windowNoTitle,Window_windowActionBar...
//首先通过WindowStyle中设置的各种属性,对Window进行requestFeature或者setFlags
if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) {
requestFeature(FEATURE_NO_TITLE);
}
//...
if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) {
setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
}
//...根据当前sdk的版本确定是否需要menukey
WindowManager.LayoutParams params = getAttributes();
//通过a中设置的属性,设置 params.softInputMode 软键盘的模式;
//如果当前是浮动Activity,在params中设置FLAG_DIM_BEHIND并记录dimAmount的值。
//以及在params.windowAnimations记录WindowAnimationStyle
// Inflate the window decor.
int layoutResource;
int features = getLocalFeatures();
// System.out.println("Features: 0x" + Integer.toHexString(features));
if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = com.android.internal.R.layout.screen_title_icons;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
// System.out.println("Title Icons!");
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
&& (features & (1 << FEATURE_ACTION_BAR)) == 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("Progress!");
} else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
// Special case for a window with a custom title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.dialogCustomTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = com.android.internal.R.layout.screen_custom_title;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
} else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
// If no other features and not embedded, only need a title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
com.android.internal.R.attr.dialogTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
layoutResource = com.android.internal.R.layout.screen_action_bar;
} else {
layoutResource = com.android.internal.R.layout.screen_title;
}
// System.out.println("Title!");
} else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
layoutResource = com.android.internal.R.layout.screen_simple_overlay_action_mode;
} else {
// Embedded, so no decoration is needed.
layoutResource = com.android.internal.R.layout.screen_simple;
// System.out.println("Simple!");
}
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
//...
return contentParent;
}
}
代码也比较长,首先getWindowStyle在当前的Window的theme中获取我们的Window中定义的属性。具体参考:\frameworks\base\core\res\res\values\attrs.xml
然后就根据这些属性的值,对我们的Window各种requestFeature,setFlags等等。所以这里就是解析我们为Activity设置theme的地方,至于theme一般可以在AndroidManifest里面进行设置。
接下来就到关键的部分了,21-75行:通过对features和mIsFloating的判断,为layoutResource进行赋值,至于值可以为R.layout.screen_custom_title;R.layout.screen_action_bar;等等。至于features,除了theme中设置的,我们也可以在Activity的onCreate的setContentView之前进行requestFeature,也解释了,为什么需要在setContentView前调用requestFeature设置全屏什么的。
得到了layoutResource以后,78行,通过LayoutInflater把布局转化成view,加入到我们的decor,即传入的mDecor中。
接下来81行:通过mDecor.findViewById传入R.id.content(相信这个id大家或多或少都听说过),返回mDecor(布局)中的id为content的View,一般为FrameLayout。
好了,可以看到我们的mDecor是一个FrameLayout,然后会根据theme去选择系统中的布局文件,将布局文件通过inflate转化为view,加入到mDecor中;这些布局文件中都包含一个id为content的FrameLayout,将其引用返回给mContentParent。
等我们的mContentParent有值了以后,还记得干嘛了么?再贴一次PhoneWindow的setContentView
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
有了mContentParent,然后把我们写的布局文件通过inflater加入到mContentParent中。
关于R.layout.xxx可以在frameworks\base\core\res\res\layout里面进行查看。
例如:R.layout.screen_custom_title.xml
<LinearLayout xmlns:android="schemas.android.com/apk/res/and…"
android:orientation="vertical"
android:fitsSystemWindows="true">
<ViewStub android:id="@+id/action_mode_bar_stub"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout android:id="@android:id/title_container"
android:layout_width="match_parent"
android:layout_height="?android:attr/windowTitleSize"
style="?android:attr/windowTitleBackgroundStyle">
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
上面的title_container是用来放自定义Title的容器,而下面的content就是放置我们设置的布局的容器。关于自定义Title例子,大家可以百度下。
到此,我们的setContentView就分析完成了,我们可以回顾一下:
首先初始化mDecor,即DecorView为FrameLayout的子类。就是我们整个窗口的根视图了。
然后,根据theme中的属性值,选择合适的布局,通过infalter.inflater放入到我们的mDecor中。
在这些布局中,一般会包含ActionBar,Title,和一个id为content的FrameLayout。
最后
赠送大家一套完整的Android学习资料吧。
以前一直是自己在网上东平西凑的找,找到的东西也是零零散散,很多时候都是看着看着就没了,时间浪费了,问题却还没得到解决,很让人抓狂。
后面我就自己整理了一套资料,还别说,真香!
资料有条理,有系统,还很全面,我不方便直接放出来,大家可以先看看有没有用得到的地方吧。
附上白嫖地址:《Android架构视频+BATJ面试专题PDF+学习笔记》