前面咱们已经学过《Android 自定义 view(三)—— onDraw 方法理解》,那么接下咱们还须要继续去理解自定义view里面的onMeasure 方法html
推荐文章:canvas
http://blog.csdn.net/a396901990/article/details/36475213?utm_source=tuicool&utm_medium=referral(1)通常状况重写onMeasure()方法做用是为了自定义View尺寸的规则,若是你的自定义View的尺寸是根据父控件行为一致,就不须要重写onMeasure()方法
(2)若是不重写onMeasure方法,那么自定义view的尺寸默认就和父控件同样大小,固然也能够在布局文件里面写死宽高,而重写该方法能够根据本身的需求设置自定义view大小ide
(0)onMeasure (int widthMeasureSpec, int heightMeasureSpec)是view本身的方法函数
(1)onMeasure 方法简单的理解就是是用于测量视图的大小,主要是用来测量本身和内容的来肯定宽度和高度 布局
(2)onMeasure有两个参数 ( int widthMeasureSpec, int heightMeasureSpec),该参数表示控件可得到的空间以及关于这个空间描述的元数据.测试
(3)widthMeasureSpec和heightMeasureSpec这两个值一般状况下都是由父视图通过计算后传递给子视图的,说明父视图会在必定程度上决定子视图的大小。ui
在测量自定义view的大小以前,咱们须要认识一个类MeasureSpec,它封装了父布局传递给子布局的布局要求,每一个MeasureSpec表明了一组宽度和高度的要求 MeasureSpec由size和mode组成。 this
要去自定义控件上面写一段文字,根据宽度.net
/**
* Created by yishujun on 16/6/5.
*/
public class YView extends View {
private Context mContext;
//定义一个paint
private Paint mPaint;orm
private String mText = "测试文字,自定义view";
//绘制时控制文本绘制的范围
private Rect mBound;
public YView(Context context) {
this(context, null);
}
public YView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public YView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
mBound = new Rect();
mPaint = new Paint();
mPaint.setTextSize(60);
mPaint.getTextBounds(mText, 0, mText.length(), mBound);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.GRAY);
mPaint.setColor(Color.RED);
canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
}
/**
* 比onDraw先执行
* <p>
* 一个MeasureSpec封装了父布局传递给子布局的布局要求,每一个MeasureSpec表明了一组宽度和高度的要求。
* 一个MeasureSpec由大小和模式组成
* 它有三种模式:UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素能够获得任意想要的大小;
* EXACTLY(彻底),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它自己大小;
* AT_MOST(至多),子元素至多达到指定大小的值。
* <p>
* 它经常使用的三个函数:
* 1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)
* 2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是咱们一般所说的大小)
* 3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式建立一个测量值(格式)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int minimumWidth = getSuggestedMinimumWidth();
final int minimumHeight = getSuggestedMinimumHeight();
Log.e("YView", "---minimumWidth = " + minimumWidth + "");
Log.e("YView", "---minimumHeight = " + minimumHeight + "");
int width = measureWidth(minimumWidth, widthMeasureSpec);
int height = measureHeight(minimumHeight, heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureWidth(int defaultWidth, int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
Log.e("YViewWidth", "---speSize = " + specSize + "");
switch (specMode) {
case MeasureSpec.AT_MOST:
defaultWidth = (int) mPaint.measureText(mText) + getPaddingLeft() + getPaddingRight();
Log.e("YViewWidth", "---speMode = AT_MOST");
break;
case MeasureSpec.EXACTLY:
Log.e("YViewWidth", "---speMode = EXACTLY");
defaultWidth = specSize;
break;
case MeasureSpec.UNSPECIFIED:
Log.e("YViewWidth", "---speMode = UNSPECIFIED");
defaultWidth = Math.max(defaultWidth, specSize);
}
return defaultWidth;
}
private int measureHeight(int defaultHeight, int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
Log.e("YViewHeight", "---speSize = " + specSize + "");
switch (specMode) {
case MeasureSpec.AT_MOST:
defaultHeight = (int) (-mPaint.ascent() + mPaint.descent()) + getPaddingTop() + getPaddingBottom();
Log.e("YViewHeight", "---speMode = AT_MOST");
break;
case MeasureSpec.EXACTLY:
defaultHeight = specSize;
Log.e("YViewHeight", "---speSize = EXACTLY");
break;
case MeasureSpec.UNSPECIFIED:
defaultHeight = Math.max(defaultHeight, specSize);
Log.e("YViewHeight", "---speSize = UNSPECIFIED");
// 1.基准点是baseline
// 2.ascent:是baseline之上至字符最高处的距离
// 3.descent:是baseline之下至字符最低处的距离
// 4.leading:是上一行字符的descent到下一行的ascent之间的距离,也就是相邻行间的空白距离
// 5.top:是指的是最高字符到baseline的值,即ascent的最大值
// 6.bottom:是指最低字符到baseline的值,即descent的最大值
break;
}
return defaultHeight;
}
}