博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
xml生成view时layout参数失效问题解决
阅读量:5937 次
发布时间:2019-06-19

本文共 5059 字,大约阅读时间需要 16 分钟。

hot3.png

在ViewGroup的默认addView 方法中, 如果发现 v 没有layout参数,则生成一个默认的layoutParams, 这个参数的layout默认是wrap_content的, 所以有时候我们在xml顶层元素写的 match_parent不生效, 原因是 LayoutInflater.inflate(int res, ViewGroup root, boolean attachToRoot) 的第二个参数root我们设置的是空, 这时候xml顶层元素设置的layout参数将统统忽略, 要想让这些参数生成v的layoutparams, 需要提供合适的 root,  因为不同的ViewGroup子类支持的layout参数是不同的。

/**     * Adds a child view. If no layout parameters are already set on the child, the     * default parameters for this ViewGroup are set on the child.     *      * 

Note: do not invoke this method from     * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)},     * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

     *     * @param child the child view to add     * @param index the position at which to add the child     *     * @see #generateDefaultLayoutParams()     */    public void addView(View child, int index) {        LayoutParams params = child.getLayoutParams();        if (params == null) {            params = generateDefaultLayoutParams();            if (params == null) {                throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");            }        }        addView(child, index, params);    }        ...         /**     * Returns a set of default layout parameters. These parameters are requested     * when the View passed to {@link #addView(View)} has no layout parameters     * already set. If null is returned, an exception is thrown from addView.     *     * @return a set of default layout parameters or null     */    protected LayoutParams generateDefaultLayoutParams() {        return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);    }

比如一个继承了LinearLayout的MyLinearLayout的初始化init方法中,生成test_layout时传入的root参数是null, 那么test_layout生成的view其实并不能填充其parent,只需将null改为this就可以解决这个问题:

View v = mLayoutInflater.inflate(R.layout.test_layout, null, false);		addView(v);

View v = mLayoutInflater.inflate(R.layout.test_layout, this, false);		addView(v);

// test_layot.xml: 
    

从下面的inflate过程可以明显的看出这一逻辑, 值得一提的是其中对 blink 标签的处理,会生成一个有闪烁效果的view  ==, BlinkLayout 是LayoutInflater的内部类,每个一个时间(500)会invalidate一次。

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {        synchronized (mConstructorArgs) {            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");            final AttributeSet attrs = Xml.asAttributeSet(parser);            Context lastContext = (Context)mConstructorArgs[0];            mConstructorArgs[0] = mContext;            View result = root;            try {                // Look for the root node.                int type;                while ((type = parser.next()) != XmlPullParser.START_TAG &&                        type != XmlPullParser.END_DOCUMENT) {                    // Empty                }                if (type != XmlPullParser.START_TAG) {                    throw new InflateException(parser.getPositionDescription()                            + ": No start tag found!");                }                final String name = parser.getName();                                                if (TAG_MERGE.equals(name)) {                   // deal with merge tag                } else {                    // Temp is the root view that was found in the xml                    View temp;                    if (TAG_1995.equals(name)) {                        temp = new BlinkLayout(mContext, attrs);                    } else {                        temp = createViewFromTag(root, name, attrs);                    }                    ViewGroup.LayoutParams params = null;                    // if root is not null, the created view will have a non-null layout param                    if (root != null) {                        params = root.generateLayoutParams(attrs);                        if (!attachToRoot) {                            // Set the layout params for temp if we are not                            // attaching. (If we are, we use addView, below)                            temp.setLayoutParams(params);                        }                    }                    if (root != null && attachToRoot) {                        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;                    }                }            } catch (XmlPullParserException e) {               ...            } finally {                // Don't retain static reference on context.                mConstructorArgs[0] = lastContext;                mConstructorArgs[1] = null;            }            Trace.traceEnd(Trace.TRACE_TAG_VIEW);            return result;        }    }

像这样就可以生成一个闪烁的text view :

    

另外,在inflate 时如果提供了 containerView, 那么被inflate的view 会执行一次 onLayout, 如果没有, 那么只有等到view被 addView 进一个parentView后才能执行layout。

转载于:https://my.oschina.net/u/255456/blog/341781

你可能感兴趣的文章
苹果开发者账号--关于邓白氏编码的申请
查看>>
[怪谈]唯有数学不会因时代的变迁而没落
查看>>
Nginx upstream的几种分配方式
查看>>
办公室,手机上网不用愁
查看>>
SCCM 2012系列11 补丁分发下
查看>>
一次网站性能排查实录
查看>>
linux重启后出现control+D错误的解决
查看>>
数据库方言
查看>>
读书笔记-大教堂与集市
查看>>
【闲聊产品】之五:谁来背黑锅?
查看>>
JAVA还是C?
查看>>
iptables从入门到精通
查看>>
“无现金”社会来临,你还有安全感吗?
查看>>
Exchange 2013部署系列之(五)NLB负载均衡
查看>>
可怕的云计算
查看>>
赛门铁克开启“容灾即服务”时代
查看>>
Windows Live & Windows Phone 7
查看>>
oracle 查看表所占用的空间大小
查看>>
两种底层数据层操作时的架构方式,你喜欢那种?
查看>>
常用的原型开发工具
查看>>