Activity源码浅析-DecorView
来源:互联网 发布:剑网三炮姐捏脸数据 编辑:程序博客网 时间:2024/06/09 22:16
使用Activity,我们会先在onCreate方法中,设置setContentView
public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); }
getWindow().setContentView(layoutResId)这句话是把我们的布局放到哪里了呢?
public Window getWindow() { return mWindow; }
Window是什么呢?
public abstract class Window{......}
Window:规定了顶层窗口的视觉和行为规范的抽象类。它的实例用于将最顶层的View添加到WindowManager。它提供了基本的UI规范比如背景,标题区域,默认的关键处理。
Window只有一个实例PhoneWindow
现在我们知道了Window是什么,接下来继续分析它的实例PhoneWidow:getWindow().setContentView(layoutResID);
public class PhoneWindow extends Window implements MenuBuilder.Callback { //mDecor本身或者布局添加的子View ViewGroup mContentParent; @Override public void setContentView(int layoutResID) { //如果顶层容器为null,则创建Decor if (mContentParent == null) { //接下来分析这里,创建Decor installDecor(); } ......... if (mContentParent == null) { //这里证明mContentParent是mDecor或mDecor的子View mContentParent = generateLayout(mDecor); ...... } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext()); transitionTo(newScene); } else { //将设置的布局添加到mContentView mLayoutInflater.inflate(layoutResID, mContentParent); } mContentParent.requestApplyInsets(); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } mContentParentExplicitlySet = true;}
接下来我们分析一下installDecor做了什么呢?
private void installDecor() { mForceDecorInstall = false; if (mDecor == null) { //创建Decor,接下来看generateDecor mDecor = generateDecor(-1); .......... } } else { mDecor.setWindow(this); } }
generateDecor(int featureId)创建Decor
protected DecorView generateDecor(int featureId) { .... return new DecorView(context, featureId, this, getAttributes()); }
DecorView是什么呢?
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks { ....}
DecorView实际上是一个FrameLayout
我们回到PhoneWindow的setContentView继续分析
protected ViewGroup generateLayout(DecorView decor) { 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); }//是否有title if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) { requestFeature(FEATURE_NO_TITLE); } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) { // Don't allow an action bar if there is no title. requestFeature(FEATURE_ACTION_BAR); }...//是否全屏 if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) { setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags())); } ...... // 接下来Decoview inflate 子View 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!"); } 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 = 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( R.attr.dialogCustomTitleDecorLayout, res, true); layoutResource = res.resourceId; } else { layoutResource = 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( R.attr.dialogTitleDecorLayout, res, true); layoutResource = res.resourceId; } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) { layoutResource = a.getResourceId( R.styleable.Window_windowActionBarFullscreenDecorLayout, R.layout.screen_action_bar); } else { layoutResource = R.layout.screen_title; } // System.out.println("Title!"); } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) { layoutResource = R.layout.screen_simple_overlay_action_mode; } else { // Embedded, so no decoration is needed. layoutResource = R.layout.screen_simple; // System.out.println("Simple!"); } mDecor.startChanging(); //mDecor添加对应的布局 mDecor.onResourcesLoaded(mLayoutInflater, layoutResource); ...... //证明是Decor的子View ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); if (contentParent == null) { throw new RuntimeException("Window couldn't find content container view"); } ......return contentParent;}
通过上面代码可以知道generateLayout获取了Window的属性,比如是否全屏,是否悬浮,是否有title等。然后根据这些属性来选择默认的布局文件进行映射,比如screen_title.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:fitsSystemWindows="true"> <!-- Popout bar for action modes --> <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" android:theme="?attr/actionBarTheme" /> <FrameLayout android:layout_width="match_parent" android:layout_height="?android:attr/windowTitleSize" style="?android:attr/windowTitleBackgroundStyle"> <TextView android:id="@android:id/title" style="?android:attr/windowTitleStyle" android:background="@null" android:fadingEdge="horizontal" android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> <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" /></LinearLayout>
然后通过
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource); ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
实现mDecorView添加默认布局,和通过id获取子view:contentParent
通过上面的源码,我们就对Activity的布局层级有了一个清晰的认识,结构如图:
阅读全文
0 0
- Activity源码浅析-DecorView
- DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- android DecorView 浅析
- Android DecorView浅析
- Android DecorView浅析
- Android DecorView浅析
- win10 设置定时关机
- maven添加本地验证码kaptcha jar包
- Java修饰符
- ios 基础Block为什么用copy修饰
- JSON.stringify() 和 JSON.parse()
- Activity源码浅析-DecorView
- 人脸识别数据集之MS-Celeb-1M
- PTA 4-5 家谱处理(建树做法)
- EPSG:4326
- Python 三目运算,列表解析,装饰器,迭代器和生成器
- azkaban上传时卡在那不动
- 马云:“人工智能” 这几个字听起来,我就很生气
- 关于hive自定义JsonSerde处理json
- tabbarController的使用