andriod 动态加载xml布局 莫名奇妙丢失xml根布局属性?

问题:

我有一个FrameLayout(后面简称frame),我有一个需求,是动态向这个frame中添加一个使用xml定义子view(后面简称xmlview),一般的方法都是使用LayoutInflater动态inflate一个view,然后调用

frame.addViiew,结果发现xmlview的根布局的layout_width 和 layout_height 一直不生效,这特么是什么鬼,不管怎么改都不行,撞鬼了么


原因剖析:

主要原因还是我们对LayoutInflater类中的inflate函数认知不清导致的。

首先,先贴上相关源码:

/**
     * Inflate a new view hierarchy from the specified xml resource. Throws
     * {@link InflateException} if there is an error.
     * 
     * @param resource ID for an XML layout resource to load (e.g.,
     *        <code>R.layout.main_page</code>)
     * @param root Optional view to be the parent of the generated hierarchy.
     * @return The root View of the inflated hierarchy. If root was supplied,
     *         this is the root View; otherwise it is the root of the inflated
     *         XML file.
     */
    public View inflate(int resource, ViewGroup root) {
        return inflate(resource, root, root != null);
    }

/**
     * Inflate a new view hierarchy from the specified xml resource. Throws
     * {@link InflateException} if there is an error.
     * 
     * @param resource ID for an XML layout resource to load (e.g.,
     *        <code>R.layout.main_page</code>)
     * @param root Optional view to be the parent of the generated hierarchy (if
     *        <em>attachToRoot</em> is true), or else simply an object that
     *        provides a set of LayoutParams values for root of the returned
     *        hierarchy (if <em>attachToRoot</em> is false.)
     * @param attachToRoot Whether the inflated hierarchy should be attached to
     *        the root parameter? If false, root is only used to create the
     *        correct subclass of LayoutParams for the root view in the XML.
     * @return The root View of the inflated hierarchy. If root was supplied and
     *         attachToRoot is true, this is root; otherwise it is the root of
     *         the inflated XML file.
     */
    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();
        }
    }

大家已经注意到了,两个参数的inflate方法其实也是调用三个参数的inflate方法,

如果调用(下面伪代码中 frameParent 不为空 )

inflate(R.layout.demo, frameParent)   则相当于是调用了inflate(R.layout.demo, frameParent, true)


让我们接下来深入infalte具体的执行代码(篇幅问题,只截取了最重要的部分)

// Temp is the root view that was found in the xml
                    View temp;<span style="color:#ff0000;">//这个temp就是xml的根view</span>
                    if (TAG_1995.equals(name)) {
                        temp = new BlinkLayout(mContext, attrs);
                    } else {
                        temp = createViewFromTag(root, name, attrs);
                    }

                    ViewGroup.LayoutParams params = null;

                    if (root != null) { //这个root就是使用inflate时候的第二个参数 如果root为null,xml根view<span style="font-family: Arial, Helvetica, sans-serif;">则</span><span style="font-family: Arial, Helvetica, sans-serif;">会丢失width height 属性</span>
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);<span style="color:#ff0000;">//这个大家可以自行研究下 就是根据xml中声明的属性来创建的</span>
                        if (!attachToRoot) { //只要你传了root进来,不管是否attch xml的根都会有自己原先在xml设置的属性 
                            // Set the layout params for temp if we are not
                            // attaching. (If we are, we use addView, below)
                            temp.setLayoutParams(params);
                        }
                    }

                    if (DEBUG) {
                        System.out.println("-----> start inflating children");
                    }
                    // Inflate all children under temp
                    rInflate(parser, temp, attrs, true);
                    if (DEBUG) {
                        System.out.println("-----> done inflating children");
                    }

                    // We are supposed to attach all the views we found (int temp)
                    // to root. Do that now.
                    if (root != null && attachToRoot) {<span style="font-family: Arial, Helvetica, sans-serif;">//如果使用了attachToRoot 那么xml的布局将会直接添加到root中 </span>

                        root.addView(temp, params);
                    }

                    // Decide whether to return the root that was passed in or the
                    // top view found in xml.
                    if (root == null || !attachToRoot) {//此处决定返回什么视图
                        result = temp;
                    }

相信通过上面的代码大家已经知道为什么xml中根view会丢失width以及heigh属性了吧,原因就是:你在调用inflate函数时候,传了一个null的父布局。
inflate(R.layout.demo, null)  

接下来还有一个小点要讲述一下:

inflate(R.layout.demo, null) 返回的view 是 xml本身的根view 丢失了设置的layout_width 以及 layout_height
inflate(R.layout.demo, parent)以及 inflate(R.layout.demo, parent, true)  返回的view 是 parent ,而不是xml的根布局</span>
inflate(R.layout.demo, parent, false)  返回的view是 xml的根view 但是此时他拥有xml中设置的 layout_width和 layout_height 

 到这,这个问题已经理清了。 
 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值