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

前端之家收集整理的这篇文章主要介绍了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,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,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,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,false) 返回的view是 xml的根view 但是此时他拥有xml中设置的 layout_width和 layout_height

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

猜你在找的XML相关文章