Android XML布局与View之间的转换

本文介绍了Android中XML布局如何转换成View的过程。从源码层面,通过分析Activity的setContentView方法,展示了XML根节点名的获取,以及如何通过构造函数创建临时View。讨论了自定义View为何需要重载特定构造函数,并探讨了当inflate时父布局为null时,布局宽度和高度设置失效的问题。
摘要由CSDN通过智能技术生成

Android的布局方式有两种,一种是通过xml布局,一种是通过java代码布局,两种布局方式各有各的好处,当然也可以相互混合使用。很多人都习惯用xml布局,那xml布局是如何转换成view的呢?本文从源码的角度来简单分析下整个过程。

首先,创建一个新的项目,默认生成一个activity,其中xml布局很简单,就一个RelativeLayout套了一个ImageView,代码及效果如下:

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

其中关键之处就在于调用了父类Activity的setContentView方法:

    /**
     * Set the activity content from a layout resource.  The resource will be
     * inflated, adding all top-level views to the activity.
     * 
     * @param layoutResID Resource ID to be inflated.
     */
    public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
    }

getWindow返回的是PhoneWindow实例,那我们直接来看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) {
            cb.onContentChanged();
        }
    }

我们知道每个activity实际都对应一个PhoneWindow,拥有一个顶层的DecorView,DecorView继承自FrameLayout,作为根View,其中包含了一个标题区域和内容区域,这里的mContentParent就是其内容区域。关于PhoneWindow和DecorView的具体内容,读者可自行查阅。这段代码的意思很简单,如果DecorView的内容区域为null,就先初始化,否则就先把内容区域的子View全部移除,最后再引入layout布局,所以,关键在于mLayoutInflater.inflate(layoutResID, mContentParent); 代码继续往下看:

    public View inflate(int resource, ViewGroup root) {
        return inflate(resource, root, root != null);
    }
    public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
        if (DEBUG) System.out.println("INFLATING from resource: " + resource);
        XmlResourceParser parser = getContext().getResources().getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }

这里首先根据layout布局文件的Id生成xml资源解析器,然后再调用inflate(parser, root, attachToRoot)生成具体的view。XmlResourceParser是继承自XmlPullParser和AttributeSet的接口,这里的parser其实是XmlBlock的内部类Parser的实例。
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
        synchronized (mConstructorArgs) {
            final AttributeSet attrs = Xml.asAttributeSet(parser);
            Context lastContext = (Context)mConstructorArgs[0];
            mConstructorArgs[0] = mContext;
     
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值