Activity的setContentView()
public void setContentView(View view, ViewGroup.LayoutParams params) {
getWindow().setContentView(view, params);
initWindowDecorActionBar();
}
调用了Window的setContentView(),然后创建一个ActionBar。
Window的setContentView()
abstract class Window:概括了Android窗口的基本属性和基本功能。
顶级窗口外观和行为策略的抽象基类。这个类的实例用做顶级View添加进window manager。提供标准UI规范如背景、标题区域、默认键盘进程等。
而window在整个布局的id就是R.id.content
Window的实现类PhoneWindow的setContentView()
@Override
public void setContentView(int layoutResID) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
// before this happens.
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
首先判断mContentParent是否为null,是则调用installDecor(),否则移除其内部所有的子Views,然后通过LayoutInflater.inflate将我们传入的layout放置到mContentParent中。
最后设置Callback(即window所属Activity),CallBack接口拦截键盘、面板、菜单等操作。
installDecor()
private void installDecor() {
// 首先判断mDecor是否为空,成立就创建一个新的Decor并初始化。
if (mDecor == null) {
mDecor = generateDecor();
// 当子View都不需要焦点时,decor才获取焦点。
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
//
if (mContentParent == null) {
// 生成mContentParent
mContentParent = generateLayout(mDecor);
// 根据定义的样式设置title,图标,background等。
// 如果调用没自定义TransitionManager就创建一个新的。
}
}
Decor继承自FrameLayout。
generateDecor()
protected ViewGroup generateLayout(DecorView decor) {
// Apply data from current theme.
// 首先通过WindowStyle中设置的各种属性,对Window进行requestFeature或者setFlags
TypedArray a = getWindowStyle();
mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);
int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
& (~getForcedWindowFlags());
if (mIsFloating) {
setLayout(WRAP_CONTENT, WRAP_CONTENT);
setFlags(0, flagsToUpdate);
} else {
setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
}
//...根据当前sdk的版本确定是否需要menukey
final Context context = getContext();
......
if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {
setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE);
} else {
setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);
}
//通过a中设置的属性,设置 params.softInputMode 软键盘的模式;
//如果当前是浮动Activity,在params中设置FLAG_DIM_BEHIND并记录dimAmount的值。
//以及在params.windowAnimations记录WindowAnimationStyle
......
// 所有的都做完了只是window没嵌入。否则,值从容器继承
if (getContainer() == null) {
if (mBackgroundDrawable == null) {
if (mBackgroundResource == 0) {
mBackgroundResource = a.getResourceId(
R.styleable.Window_windowBackground, 0);
}
if (mFrameResource == 0) {
mFrameResource = a.getResourceId(R.styleable.Window_windowFrame, 0);
}
mBackgroundFallbackResource = a.getResourceId(
R.styleable.Window_windowBackgroundFallback, 0);
if (false) {
System.out.println("Background: "
+ Integer.toHexString(mBackgroundResource) + " Frame: "
+ Integer.toHexString(mFrameResource));
}
}
mElevation = a.getDimension(R.styleable.Window_windowElevation, 0);
mClipToOutline = a.getBoolean(R.styleable.Window_windowClipToOutline, false);
mTextColor = a.getColor(R.styleable.Window_textColor, Color.TRANSPARENT);
}
// 填充window decor
// 通过对features和mIsFloating的判断,为layoutResource进行赋值,所以requestFeature要在setContentView之前进行
int layoutResource;
int features = getLocalFeatures();
// System.out.println("Features: 0x" + Integer.toHexString(features));
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
layoutResource = R.layout.screen_swipe_dismiss;
} else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = R.layout.screen_title_icons;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
// System.out.println("Title Icons!");
}
......
mDecor.startChanging();
// 把layout转化成view添加到decor
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
// 通过mDecor.findViewById传入R.id.content
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
if (contentParent == null) {
throw new RuntimeException("Window couldn't find content container view");
}
......
// 剩余设置--背景和标题--只适用于顶级窗口
if (getContainer() == null) {
......
}
mDecor.finishChanging();
return contentParent;
}