View的测量问题

我们知道,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的测量大小。无论是哪一方不遵循着个契约, 都会造成布局错乱的可能。

你可能感兴趣的:(View的测量问题)