Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義控件系列一:如何測量控件尺寸

Android自定義控件系列一:如何測量控件尺寸

編輯:關於Android編程

 

測量控件尺寸(寬度、高度)是開發自定義控件的第一步,只有確定尺寸後才能開始畫(利用canvas在畫布上畫,我們所使用的控件實際上都是這樣畫上去的)。當然,這個尺寸是需要根據控件的各個部分計算出來的,比如:padding、文字大小,間距等。

 

非容器控件的onMeasure

下面我們就來看看如何給非容器控件(即直接extends View)這只尺寸的:

1.@Override2.protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {3.setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));4.}

通過重寫onMeasure()方法來設置尺寸。這個方法實際是由容器控件(LinearLayout、RelativeLayout)來調用的,以便容器控件知道我需要分配給你多大空間或尺寸。

計算完尺寸後,最終調用setMeasuredDimension()來設置。比如,我要創建個 寬度是200px,高度是100px的控件,就可以setMeasuredDimension(200, 100)。

注意setMeasuredDimension()接收的值是px值,而不是dp值,所以我們不可能像上面那樣將尺寸寫固定的。如何做那:

參數 int widthMeasureSpec, int heightMeasureSpec 是指明控件可獲得的空間以及關於這個空間描述的元數據,是與布局文件中android:layout_width、android:layout_height相聯系的。如何使用:

01. /**02.* 計算組件寬度03.*/04.private int measureWidth(int widthMeasureSpec) {05.int result;06.int specMode = MeasureSpec.getMode(widthMeasureSpec);07.int specSize = MeasureSpec.getSize(widthMeasureSpec);08. 09.if (specMode == MeasureSpec.EXACTLY) {//精確模式10.result = specSize;11.} else {12.result = getDefaultWidth();//最大尺寸模式,getDefaultWidth方法需要我們根據控件實際需要自己實現13.if (specMode == MeasureSpec.AT_MOST) {14.result = Math.min(result, specSize);15.}16.}17.return result;18.}

調用MeasureSpec.getMode(measureSpec),可以獲得設置尺寸的mode(模式)。

mode共有三種情況,取值分別為:

MeasureSpec.UNSPECIFIED,MeasureSpec.EXACTLY,MeasureSpec.AT_MOST。

 

MeasureSpec.EXACTLY是精確尺寸,當我們將控件的layout_width或layout_height指定為具體數值時如andorid:layout_width=50dip,或者為FILL_PARENT是,都是控件大小已經確定的情況,都是精確尺寸。

MeasureSpec.AT_MOST是最大尺寸,當控件的layout_width或layout_height指定為WRAP_CONTENT時,控件大小一般隨著控件的子空間或內容進行變化,此時控件尺寸只要不超過父控件允許的最大尺寸即可。因此,此時的mode是AT_MOST,size給出了父控件允許的最大尺寸。

MeasureSpec.UNSPECIFIED是未指定尺寸,這種情況不多,一般都是父控件是AdapterView,通過measure方法傳入的模式。

 

measureWidth() 方法是個固定實現,幾乎不用改, 唯一需要我們實現的就是getDefaultWidth()。即,當mode處於最大模式下,此時父容器會將他所能給你的或者說目前剩余的最大空間給你。你只能在這個空間內設定控件尺寸。一個簡單的類似TextView的getDefaultWidth()的實現:

1.private void getDefaultWidth(){2.int txtWidth = (int)this.paint.measureText(this.text);3.return txtWidth + this.paddingLeft + this.paddingRight;4.}

 

上面說了寬度的測量,高度同理:

01. /**02.* 計算組件高度03.*/04.private int measureHeight(int measureSpec) {05.int result;06.int specMode = MeasureSpec.getMode(measureSpec);07.int specSize = MeasureSpec.getSize(measureSpec);08. 09.if (specMode == MeasureSpec.EXACTLY) {10.result = specSize;11.} else {12.result = getDefaultHeight();13.if (specMode == MeasureSpec.AT_MOST) {14.result = Math.min(result, specSize);15.}16.}17.return result;18.}

有了上面的實現,我們就可以在布局文件中使用控件時,通過android:layout_width、android:layout_height來自定義控件的寬度、高度。

 

容器控件的onMeasure

 

容器控件一般是繼承ViewGroup,ViewGroup是個抽象類,本身沒有實現onMeasure,但是他的子類都有各自的實現,通常他們都是通過measureChildWithMargins函數或者其他類似於measureChild的函數來遍歷測量子View,被GONE的子View將不參與測量,當所有的子View都測量完畢後,才根據父View傳遞過來的模式和大小來最終決定自身的大小.

在測量子View時,會先獲取子View的LayoutParams,從中取出寬高,如果是大於0,將會以精確的模式加上其值組合成MeasureSpec傳遞子View,如果是小於0,將會把自身的大小或者剩余的大小傳遞給子View,其模式判定在前面表中有對應關系.

ViewGroup一般都在測量完所有子View後才會調用setMeasuredDimension()設置自身大小。

 

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved