我们知道,onMeasure(int widthMeasureSpec, int heightMeasureSpec)
方法中,测量当前视图的大小,需要考虑父视图传给的参数限制。那么要不理睬父容器的限制(即不用上述方法中的两个参数),自己确定大小会有什么问题呢?
回答这个问题,我们需要明白一些前置知识。
由于一个View一般是不会单独存在的,通常会嵌套在其他ViewGroup中,要是子View绘制区域超出父View给出大小时,是要截断的(这里有例外情况,在父View中,将clipChildren设置为false,子View绘制区域可以超出)。
例子:
class ChildView :View {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
//无视父视图传来的参数,直接给当前View设置宽高
setMeasureDimension(400, 400)
}
override fun onDraw(canvas: Canvas) {
//简单涂个颜色
canvas.drawColor(Color.BLUE)
}
}
class ParentView:ViewGroup{
init{
addChild(ChildView(context))
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
val child = getChildAt(0)
//一般情况下,我们是要先要根据child的测量大小,padding来放置的,
//为了简单,不管padding
//我们作为父视图,有权如何防止子View。要求子View大小小于200,这个限制在onMeasure中传递给子View
child.layout(0, 0, 200, 200)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
//这里给子View传递一个测量参数,从而调用子View的onMeasure()方法
//从而告知子View的大小应该100的,否则父View没法好好处理
val child = getChildAt(0)
val measureSpec=MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY)
child.measure(measureSpec,measureSpec)
}
}
从上面的例子中看,在子View的测量过程中,父视图需要调用child.measure(),将一些大小要求传递给子View的,子View在onMeasure()方法中,获取参数,在父View的布局要求范围内,设置子View的测量大小。无论是哪一方不遵循着个契约, 都会造成布局错乱的可能。
网友评论