Android View.onMeasure方法詳解及實例
Android View.onMeasure方法詳解及實例
View在屏幕上顯示出來要先經(jīng)過measure(計算)和layout(布局).
1、什么時候調(diào)用onMeasure方法?
當(dāng)控件的父元素正要放置該控件時調(diào)用.父元素會問子控件一個問題,“你想要用多大地方???”,然后傳入兩個參數(shù)——widthMeasureSpec和heightMeasureSpec.
這兩個參數(shù)指明控件可獲得的空間以及關(guān)于這個空間描述的元數(shù)據(jù).
更好的方法是你傳遞View的高度和寬度到setMeasuredDimension方法里,這樣可以直接告訴父控件,需要多大地方放置子控件.
接下來的代碼片段給出了如何重寫onMeasure.注意,調(diào)用的本地空方法是來計算高度和寬度的.它們會譯解widthHeightSpec和heightMeasureSpec值,并計算出合適的高度和寬度值.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
// Return measured widget height.
}
private int measureWidth(int measureSpec) {
// Return measured widget width.
}
邊界參數(shù)——widthMeasureSpec和heightMeasureSpec ,效率的原因以整數(shù)的方式傳入。在它們使用之前,首先要做的是使用MeasureSpec類的靜態(tài)方法getMode和getSize來譯解,如下面的片段所示:
int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec);
依據(jù)specMode的值,(MeasureSpec有3種模式分別是UNSPECIFIED, EXACTLY和AT_MOST)
- 如果是AT_MOST,specSize 代表的是最大可獲得的空間;
- 如果是EXACTLY,specSize 代表的是精確的尺寸;
- 如果是UNSPECIFIED,對于控件尺寸來說,沒有任何參考意義。
2、那么這些模式和我們平時設(shè)置的layout參數(shù)fill_parent, wrap_content有什么關(guān)系呢?
經(jīng)過代碼測試就知道,當(dāng)我們設(shè)置width或height為fill_parent時,容器在布局時調(diào)用子 view的measure方法傳入的模式是EXACTLY,因為子view會占據(jù)剩余容器的空間,所以它大小是確定的。
而當(dāng)設(shè)置為 wrap_content時,容器傳進(jìn)去的是AT_MOST, 表示子view的大小最多是多少,這樣子view會根據(jù)這個上限來設(shè)置自己的尺寸。當(dāng)子view的大小設(shè)置為精確值時,容器傳入的是EXACTLY, 而MeasureSpec的UNSPECIFIED模式目前還沒有發(fā)現(xiàn)在什么情況下使用。
View的onMeasure方法默認(rèn)行為是當(dāng)模式為UNSPECIFIED時,設(shè)置尺寸為mMinWidth(通常為0)或者背景drawable的最小尺寸,當(dāng)模式為EXACTLY或者AT_MOST時,尺寸設(shè)置為傳入的MeasureSpec的大小。
有個觀念需要糾正的是,fill_parent應(yīng)該是子view會占據(jù)剩下容器的空間,而不會覆蓋前面已布局好的其他view空間,當(dāng)然后面布局子 view就沒有空間給分配了,所以fill_parent屬性對布局順序很重要。以前所想的是把所有容器的空間都占滿了,難怪google在2.2版本里把fill_parent的名字改為match_parent.
在兩種情況下,你必須絕對的處理這些限制。在一些情況下,它可能會返回超出這些限制的尺寸,在這種情況下,你可以讓父元素選擇如何對待超出的View,使用裁剪還是滾動等技術(shù)。
接下來的框架代碼給出了處理View測量的典型實現(xiàn):
java代碼:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredHeight = measureHeight(heightMeasureSpec);
int measuredWidth = measureWidth(widthMeasureSpec);
setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
// Default size if no limits are specified.
int result = 500;
if (specMode == MeasureSpec.AT_MOST){
// Calculate the ideal size of your
// control within this maximum size.
// If your control fills the available
// space return the outer bound.
result = specSize;
}
else if (specMode == MeasureSpec.EXACTLY){
// If your control can fit within these bounds return that value.
result = specSize;
}
return result;
}
private int measureWidth(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
// Default size if no limits are specified.
int result = 500;
if (specMode == MeasureSpec.AT_MOST){
// Calculate the ideal size of your control
// within this maximum size.
// If your control fills the available space
// return the outer bound.
result = specSize;
}
else if (specMode == MeasureSpec.EXACTLY){
// If your control can fit within these bounds return that value.
result = specSize;
}
return result;
}
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
Android?Studio實現(xiàn)音樂播放器的全過程(簡單易上手)
這篇文章主要給大家介紹了關(guān)于Android?Studio實現(xiàn)音樂播放器的相關(guān)資料,文中通過實例代碼以及圖文介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2022-02-02
viewpager+photoview實現(xiàn)圖片查看器
這篇文章主要為大家詳細(xì)介紹了viewpager+photoview實現(xiàn)圖片查看器,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
Android自定義view之利用drawArc方法實現(xiàn)動態(tài)效果(思路詳解)
這篇文章主要介紹了Android自定義view之利用drawArc方法實現(xiàn)動態(tài)效果,drawArc方法包含了五個參數(shù),具體細(xì)節(jié)在本文中給大家提到過,需要的朋友可以參考下2021-08-08
微信或手機瀏覽器在線顯示office文件(已測試ios、android)
這篇文章主要介紹了微信或手機瀏覽器在線顯示office文件,已測試ios、android,感興趣的小伙伴們可以參考一下2016-06-06

