我們知道丐吓,onMeasure(int widthMeasureSpec, int heightMeasureSpec)
方法中寸认,測量當(dāng)前視圖的大小玖姑,需要考慮父視圖傳給的參數(shù)限制妒蔚。那么要不理睬父容器的限制(即不用上述方法中的兩個參數(shù))疮鲫,自己確定大小會有什么問題呢蘸劈?
回答這個問題昏苏,我們需要明白一些前置知識。
由于一個View一般是不會單獨(dú)存在的威沫,通常會嵌套在其他ViewGroup中贤惯,要是子View繪制區(qū)域超出父View給出大小時,是要截?cái)嗟模ㄟ@里有例外情況棒掠,在父View中孵构,將clipChildren設(shè)置為false,子View繪制區(qū)域可以超出)烟很。
例子:
class ChildView :View {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
//無視父視圖傳來的參數(shù)颈墅,直接給當(dāng)前View設(shè)置寬高
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)
//一般情況下,我們是要先要根據(jù)child的測量大小雾袱,padding來放置的恤筛,
//為了簡單,不管padding
//我們作為父視圖芹橡,有權(quán)如何防止子View毒坛。要求子View大小小于200,這個限制在onMeasure中傳遞給子View
child.layout(0, 0, 200, 200)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
//這里給子View傳遞一個測量參數(shù)僻族,從而調(diào)用子View的onMeasure()方法
//從而告知子View的大小應(yīng)該100的粘驰,否則父View沒法好好處理
val child = getChildAt(0)
val measureSpec=MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY)
child.measure(measureSpec,measureSpec)
}
}
從上面的例子中看,在子View的測量過程中述么,父視圖需要調(diào)用child.measure()蝌数,將一些大小要求傳遞給子View的,子View在onMeasure()方法中度秘,獲取參數(shù)顶伞,在父View的布局要求范圍內(nèi)饵撑,設(shè)置子View的測量大小。無論是哪一方不遵循著個契約, 都會造成布局錯亂的可能唆貌。