Android系統給我們提供了一個設計短小精悍卻功能強大的類——MeasureSpec類,通過它來幫助我們測量View。MeasureSpec是一個32位的int值,其中高2位位測量的模式,低30位為測量的大小,在計算中使用位運算的原因是為了提高并優化效率。——Android群英傳
建立MyView類,繼承View。
public class MyView extends View {
public MyView(Context context) {
super(context);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 對View進行測量
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
/**
* 計算寬度
*
* @param measureSpec
* @return
*/
private int measureWidth(int measureSpec) {
int result = ;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
//MeasureSpec共3種測量模式
//EXACZTLY 精确值模式,layout_width或者layout_height屬性設定為具體數值,或指定為match_parent時
//AT_MOST 最大值模式,layout_width或者layout_height屬性設定為wrap_content時,此時空間尺寸隻要不超過父控件允許的最大尺寸即可
//UNSPECIFIED 不限制View大小
if (specMode == MeasureSpec.EXACTLY) { //如果為EXACZTLY模式,直接使用指定specSize
result = specSize;
} else {
result = ; //否則的話,specSize設定為200
if (specMode == MeasureSpec.AT_MOST) { //如果模式為AT_MOST模式,則取出我們指定的大小與specSize中小的那個座位最後的測量值
result = Math.min(result, specSize);
}
}
return result;
}
/**
* 計算高度(與計算寬度方法基本相同)
*
* @param measureSpec
* @return
*/
private int measureHeight(int measureSpec) {
int result = ;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = ;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
接下來,我們在布局中使用我們的MyView,設定寬高各300dp
<com.example.myview.myview.MyView
android:background="@color/colorAccent"
android:layout_width="300dp"
android:layout_height="300dp" />
- 1
- 2
- 3
- 4
運作效果如下圖所示:
此時MeasureSpec的測量模式為:EXACZTLY(精确值模式)。
那麼我們再看看,如果将寬高屬性設定為wrap_content,會是怎樣的效果,運作效果如下圖所示:
此時MeasureSpec的測量模式為:AT_MOST(最大值模式)。
由于MeasureSpec.getSize(measureSpec)比200dp更小,我們選擇了将寬高值設定為較小的那一個。
參考:https://blog.csdn.net/suyimin2010/article/details/79897057