美文网首页
Android视图布局初始化

Android视图布局初始化

作者: gczxbb | 来源:发表于2018-12-11 17:38 被阅读12次

窗体是视图的容器,视图依赖窗体,手机平台的窗体是PhoneWindow类,它的内部类DecorView是视图树形结构根视图,继承FrameLayout布局。
在Activity的attach方法,创建PhoneWindow,看一下它的构造方法。

public PhoneWindow(Context context) {
    super(context);
    mLayoutInflater = LayoutInflater.from(context);
}

创建一个LayoutInflater布局解析器。在Activity的onCreate方法设置视图布局,这也是初学者最先学习的东西。本文分析一下如何设置视图布局。


初始化布局

我们通常调用setContentView方法设置视图布局,传入参数视图布局资源ID。

public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

该方法调用窗体的setContentView方法。将布局资源ID代表的xml文件节点解析成View对象

private DecorView mDecor;//根View
private ViewGroup mContentParent;//存放解析出外部的View
private ViewGroup mContentRoot;//mDecor的直接子View

@Override
public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        //初始化mDecor,创建mContentParent和mContentRoot
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
       mContentParent.removeAllViews();
    }
    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        ...
    } else {
        //解析资源ID的View加入到mContentParent的子View中去
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
}

解析xml、创建DecorView、根据窗体特性初始化特定视图、将视图加到顶层视图中。mContentRoot是DecorView子视图,系统框架在解析时,根据Window不同Feature,选择不同的layoutResource布局资源。

//PhoneWindow的generateLayout方法。mContentRoot创建的代码段。
View in = mLayoutInflater.inflate(layoutResource, null);
//加入顶层视图。
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;

在这里,我们选择一种最简单的布局资源文件,screen_simple.xml文件。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">
    <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:id="@android:id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:foregroundInsidePadding="false"
        android:foregroundGravity="fill_horizontal|top"
        android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>

mContentRoot是screen_simple.xml文件解析出来的视图,将其加入顶层视图。通过findViewById方法解析ID节点获取mContentParent。
资源ID是com.android.internal.R.id.content,类型FrameLayout。

ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
一种简单的DecorView视图树形结构图。 一种简单的DecorView视图树形结构图.jpg

利用Layout Inspector工具查看视图层级。

redView.png 红色框content代表mContentParent视图结构,绿色框LinearLayout代表mContentRoot视图结构

总结

DecorView视图:树形结构顶层视图。
mContentRoot视图:由Android_SDK布局资源文件解析获取。
mContentParent视图:FrameLayout类型,mContentRoot其中一个子视图,装载用户setContentView传入的布局资源。另外,mContentRoot还有其他的子视图,如ActionBar,装载到ViewStub节点
setContentView方法仅负责视图布局的初始化,实现了树形层级结构,并未对视图实现测量布局和绘制。所以,此方法后,在屏幕上还无法看到视图。

相关文章

网友评论

      本文标题:Android视图布局初始化

      本文链接:https://www.haomeiwen.com/subject/zokehqtx.html