自定义View

Android自定义控件View(一) - brave-sailor - 博客园
onMeasure:测量控件的大小(加载布局时Android系统测量子view大小,子view大小通知父view,父view根据自己大小分配子view大小)

MeasureSpec:
MeasureSpec.EXACTLY:父视图希望子视图的大小是specSize中指定的大小;一般是设置了明确的值或者是MATCH_PARENT
MeasureSpec.AT_MOST:子视图的大小最多是specSize中的大小;表示子布局限制在一个最大值内,一般为WARP_CONTENT
MeasureSpec.UNSPECIFIED:父视图不对子视图施加任何限制,子视图可以得到任意想要的大小;表示子布局想要多大就多大,很少使用。

super.onMeasure(widthMeasureSpec, heightMeasureSpec)默认实现
结论:MeasureSpec.AT_MOST和MeasureSpec.EXACTLY走的是同一个分支

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {     setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),                                                                                                            getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
 }
..................
 public static int getDefaultSize(int size, int measureSpec) {
     int result = size;
     int specMode = MeasureSpec.getMode(measureSpec);
     int specSize = MeasureSpec.getSize(measureSpec);
     switch (specMode) {
         case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result =                            specSize;
     break;
 }
 return result;
 }

修改如下( MeasureSpec.AT_MOST和MeasureSpec.EXACTLY 分别处理,保证wrap_content效果):

Rect mBounds = new Rect(); if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else { mPaint.setTextSize(titleSize); mPaint.getTextBounds(titleText, 0, titleText.length(), mBounds); float textWidth = mBounds.width(); int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight()); width = desired; } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else { height = width; } /** * 最后调用父类方法,把View的大小告诉父布局。 */ setMeasuredDimension(width, height);

你可能感兴趣的:(自定义View)