@wangwangheng
2014-11-25T16:40:19.000000Z
字数 1756
阅读 2884
原理性知识
本文整理自Android LayoutInflater深度解析 给你带来全新的认识
[TOC]
inflate(layoutid,null)
- 最外层的控件宽高无效
inflate(layoutid,root,false)
- 最外层控件的宽高可以正确获取
- 我们一般都使用这种方式调用
inflate(layoutid,root,true)
- 不能再AdapterView或者子类中使用,会报错
FATAL EXCEPTION:main
java.lang.UnSupportedOperationException:
addView(View,LayoutParams) is not supported in Adapter
inflate(resId , null )
只创建temp ,返回temp
inflate(resId , parent, false)
创建temp,然后执行 temp.setLayoutParams(params)
;返回temp
inflate(resId , parent, true )
创建temp,然后执行root.addView(temp, params)
;最后返回root
由上面已经能够解释:
inflate(resId , null )
不能正确处理宽和高是因为:layout_width
,layout_height
是相对了父级设置的,必须与父级的LayoutParams
一致。而此temp的getLayoutParams
为null
inflate(resId , parent,false )
可以正确处理,因为temp.setLayoutParams(params)
;这个params正是root.generateLayoutParams(attrs)
;得到的。
inflate(resId , parent,true )
不仅能够正确的处理,而且已经把resId这个view加入到了parent,并且返回的是parent,和以上两者返回值有绝对的区别,还记得文章前面的例子上,MyAdapter里面的getView报的错误:
FATAL EXCEPTION:main
java.lang.UnSupportedOperationException:
addView(View,LayoutParams) is not supported in Adapter
这是因为源码中调用了root.addView(temp, params)
;而此时的root是我们的ListView
,ListView
为AdapterView
的子类:
直接看AdapterView的源码:
@Override
public void addView(View child) {
throw new UnsupportedOperationException("addView(View) is not supported in AdapterView");
}
如果大家对自定义ViewGroup和自定义View有一定的掌握,肯定不会对onMeasure方法陌生:
ViewGroup的onMeasure方法所做的是:为childView设置测量模式和测量出来的值。
如何设置呢?就是根据LayoutParams。
如果childView的宽为:LayoutParams.MATCH_PARENT
,则设置模式为MeasureSpec.EXACTLY
,且为childView计算宽度。
如果childView的宽为:固定值(即大于0),则设置模式为MeasureSpec.EXACTLY
,且将lp.width
直接作为childView的宽度。
如果childView的宽为:LayoutParams.WRAP_CONTENT
,则设置模式为:MeasureSpec.AT_MOST
高度与宽度类似。
View的onMeasure方法:
主要做的就是根据ViewGroup传入的测量模式和测量值,计算自己应该的宽和高:
一般是这样的流程:
如果宽的模式是AT_MOST
:则自己计算宽的值。
如果宽的模式是EXACTLY
:则直接使用MeasureSpec.getSize(widthMeasureSpec)
;