重寫之前先了解MeasureSpec的specMode,一共三種類型:
EXACTLY(精確模式):父容器能夠計算出自己的大小,一般是設置為match_parent或者固定值的自定義控件。
AT_MOST(至多不超過模式):父容器指定了一個大小, View 的大小不能大於這個值,也就是父容器不能夠直接計算出自己的大小,需要先由它所有的子View自己去計算一下自己大小(measureChildren()),然后再去設置該自定義控件自己的大小(setMeasuredDimension)。一般是設置為wrap_content(最大不能超過父控件)。
UNSPECIFIED(不確定模式):父容器不對 view 有任何限制,要多大給多大,多見於ListView、scrollView或GridView等。
如下代碼所示,如果模式為Exactly,系統的設定值就會等於size;如果模式為at_most,系統設定的值就會在自身需要的值和size中取最小值
重寫onMeasure
可以看出,這里的padding是自己設置到數據中去的,否則padding值並不生效
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
mPaint.setTextSize(mTextSize);
text = String.valueOf(mCount);
mPaint.getTextBounds(text, 0, text.length(), mBounds);
float textWidth = mBounds.width();
width = (int) (getPaddingLeft() + textWidth + getPaddingRight());
}
if (heightMode == MeasureSpec.EXACTLY)
{
height = heightSize;
} else
{
mPaint.setTextSize(mTextSize);
mPaint.getTextBounds(text, 0, text.length(), mBounds);
float textHeight = mBounds.height(http://www.amjmh.com/v/BIBRGZ_558768/);
height = (int) (getPaddingTop() + textHeight + getPaddingBottom());
}
setMeasuredDimension(width, height);
}