Android OnMeasure是ViewGroup中用於確定視圖大小的方法,它掌握了視圖在屏幕上的高度和寬度,而這些信息又是布局和繪製所必需的。在這篇文章中,我將從以下幾個方面進行詳細闡述OnMeasure的用處與實現原理。
一、OnMeasure的作用
OnMeasure是Android布局中最為關鍵的方法之一,它在布局時確定視圖的大小。當ViewGroup被測量時,每個子視圖的OnMeasure方法都會被調用,ViewGroup就能在得到自己的即將使用的尺寸之後,調用子視圖的OnLayout方法,以達到正確繪製的效果。
OnMeasure方法實際上是兩個部分:測量模式和測量值。單獨一個測量模式是沒法確定測量大小(測量值)的。
MeasureSpec是Android中非常重要的一個類,它表示了一個ViewGroup上的子視圖的布局要求。MeasureSpec是由一個模式值和大小組成的,僅僅知道模式是沒有用的,需要同時知道大小。
MeasureSpec由高2位代表模式,低30位表示大小。模式定義如下:
- UNSPECIFIED(不確定模式)–視圖想要多大就可以多大
- EXACTLY(精確模式)–視圖必須恰好fill_parent,match_parent(-1dp)或者一個確定的大小
- AT_MOST(至多模式)–視圖可以是任何大小,但不能比fill_parent還要大
二、OnMeasure的實現方式
在編寫自定義視圖時,我們可以需要重寫其OnMeasure方法。下面是一個自定義視圖的例子:
public class MyView extends View { public MyView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int desiredWidth = 100; int desiredHeight = 100; int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width; int height; //確定寬度大小 if (widthMode == MeasureSpec.EXACTLY) { //父視圖要求一個具體的大小 width = widthSize; } else if (widthMode == MeasureSpec.AT_MOST) { //調整為目標尺寸或更小 width = Math.min(desiredWidth, widthSize); } else { //unspecified width = desiredWidth; } //確定高度大小 if (heightMode == MeasureSpec.EXACTLY) { //父視圖要求一個具體的大小 height = heightSize; } else if (heightMode == MeasureSpec.AT_MOST) { //調整為目標尺寸或更小 height = Math.min(desiredHeight, heightSize); } else { //unspecified height = desiredHeight; } //重寫後,調用此方法讓ViewGroup知道子視圖的大小 setMeasuredDimension(width, height); } }
這個例子中的MyView是一個非常簡單的自定義View,它只是繪製了一些“虛假”內容,但是展示了如何實現OnMeasure方法。OnMeasure方法在這個例子中通過制定一個預期的大小和測量規則來獲取大小和規則,具體實現如下:
- 從MeasureSpec中解析出測量模式(mode)和測量值(size)
- 如果mode是EXACTLY,尺寸就是size。這可能是父視圖在布局時,為子視圖指定精確的大小。
- 如果mode是AT_MOST,尺寸不能大於size。這可能是父視圖在布局時,應該根據子視圖的大小來調整。可以使用整個屏幕空間,但不能比其指定大小還要大。
- 如果mode是UNSPECIFIED,這意味着視圖沿着父視圖方向想要多大就能有多大。這種情況不太常見。例子就省略了此情況。
三、OnMeasure的使用場景
在很多情況下,OnMeasure需要進行重載。
- 自定義視圖的大小
- 視圖內部的子視圖數目不固定
- 視圖內部有嵌套的自定義視圖
- 視圖的大小和位置是由其他組件決定的
在這些情況中,視圖根據其成為一個複雜或特定的類別而變得獨特。那麼我們就需要重寫OnMeasure方法,以實現自己期望的測量方式的視圖。下面的代碼中,將演示如何在一個具體情況中重載OnMeasure方法,具體實現如下:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); assert (widthMode == MeasureSpec.UNSPECIFIED || widthMode == MeasureSpec.AT_MOST); assert (heightMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.AT_MOST); int desiredWidth = 200; int desiredHeight = 200; int width = desiredWidth; int height = desiredHeight; setMeasuredDimension(width, height); }
在這個例子中,我們獲取了ViewGroup的寬度和高度的測量模式,並計算出一個指定的大小,除此之外,我們也可以重寫此方法來根據狀態調整大小。
四、OnMeasure的注意事項
在重載OnMeasure方法時,需要注意以下幾點:
- 對於自定義ViewGroup,必須調用子視圖的measure()方法來確定其大小
- 嘗試最大限度的讓布局不受限制
- 您可以根據需要以不同的方式調整視圖的大小,但必須要注意在大多數情況下,覆蓋View的onMeasure()不是一個好的設計模式
- 考慮OnLayout的實現,正確定位是在OnLayout中處理的,而不是在OnMeasure中
五、總結
Android OnMeasure是實現自定義視圖重要的方法,實現時需要注意一些細節。它通過MeasureSpec抽象類來規定測量大小和模式,以及調整ViewGroup子元素的大小。
以上是關於OnMeasure的詳細介紹,希望讀者能夠了解布局視圖的最基本方法。完成這篇文章,你已經掌握了如何利用OnMeasure打造自己的自定義視圖,同時也學習了一些重要的注意事項。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/158021.html