前面咱們已經學過《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;
}
}