1. 程式人生 > >自定義View之onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法解釋

自定義View之onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法解釋

Android中的控制元件都是View或者View的子類,因此一個自定義View可以直接繼承自View或者View的子類
當現有控制元件不能滿足我們的要求時,我們需要自己動手畫出我們想要的View。

如何去畫呢?
首先我們知道一個View的生成需要經過測量、佈局和繪製三步,分別對應View中的 onMeasure()、onLayout()和onDraw()方法。

onMeasure()方法
該方法用來測量需要繪製的View的大小,即告訴系統我有多大,系統呼叫時傳入兩個引數widthMeasureSpec和heightMeasureSpec。首先這兩個引數是由這個View的具體的ViewGroup呼叫的,
它由ViewGroup中的layout_width,layout_height和padding以及View自身的layout_margin共同決定。權值weight也是尤其需要考慮的因素,有它的存在情況可能會稍微複雜點。

兩個引數基本類似,取其一說明:
widthMeasureSpec這個值由高32位和低16位組成,高32位儲存的值叫specMode,可以通過如程式碼中所示的MeasureSpec.getMode()獲取;低16位為specSize,同樣可以由MeasureSpec.getSize()獲取。那麼specMode和specSize的作用有是什麼呢?要想知道這一點,我們需要知道程式碼中的最後一行,所有的View的onMeasure()的最後一行都會呼叫setMeasureDimension()函式的作用——這個函式呼叫中傳進去的值是View最終的檢視大小。也就是說onMeasure()中之前所作的所有工作都是為了最後這一句話服務的。

在ViewGroup中,給View分配的空間大小並不是確定的,有可能隨著具體的變化而變化,而這個變化的條件就是傳到specMode中決定的,specMode一共有三種可能:

MeasureSpec.EXACTLY:父檢視希望子檢視的大小應該是specSize中指定的。

MeasureSpec.AT_MOST:子檢視的大小最多是specSize中指定的值,也就是說不建議子檢視的大小超過specSize中給定的值。

MeasureSpec.UNSPECIFIED:我們可以隨意指定檢視的大小。

因此我們知道這個值的設計意義是為了根據ViewGroup中具體能夠提供的空間大小來指定子View的檢視大小。而檢視最終的大小由父檢視,子檢視以及程式設計師根據需要決定,良好的設計一般會根據子檢視的measureSpec設定合適的佈局大小。

下面給出自己的一個onMeasure()方法計算的實現:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //根據提供的測量值提取模式
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        //根據提供的測量值提取大小
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        /**依據得到的specMode值,如果是AT_MOST,specSize 代表的是最大可獲得的空間;如果EXACTLY,   specSize 代表的是精確的尺寸;如果是UNSPECIFIED,對於控制元件尺寸來說,沒有任何參考意義。當以EXACT方式標記測量尺寸,父元素會堅持在一個指定的精確尺寸區域放置View。在父元素問子元素要多大空間時,AT_MOST指示者會說給我最大的範圍。在很多情況下,你得到的值都是相同的。在兩種情況下,你必須絕對的處理這些限制。在一些情況下,它可能會返回超出這些限制的尺寸,在這種情況下,你可以讓父元素選擇如何對待超出的View,使用裁剪還是滾動等技術。**/
        if(widthMode == MeasureSpec.EXACTLY){
           //不需要重新計算
            widthMeasureSpec = widthSize;
        }else {
          //重新計算,這裡計算你需要繪製的檢視的寬
            widthMeasureSpec = getPaddingLeft()+getPaddingRight()+rect.width();
        }

        if(heightMode == MeasureSpec.EXACTLY){
            heightMeasureSpec = heightSize;
        }else {
            heightMeasureSpec = getPaddingTop()+getPaddingBottom()+rect.height();
        }
        //然後呼叫自setMeasuredDimension()方法將測量好的寬高儲存
        setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
    }

好了,onMeasure()方法就介紹到這裡了!

**

重點內容**# 歡迎使用Markdown編輯器寫部落格

本Markdown編輯器使用StackEdit修改而來,用它寫部落格,將會帶來全新的體驗哦:

  • Markdown和擴充套件Markdown簡潔的語法
  • 程式碼塊高亮
  • 圖片連結和圖片上傳
  • LaTex數學公式
  • UML序列圖和流程圖
  • 離線寫部落格
  • 匯入匯出Markdown檔案
  • 豐富的快捷鍵

快捷鍵

  • 加粗 Ctrl + B
  • 斜體 Ctrl + I
  • 引用 Ctrl + Q
  • 插入連結 Ctrl + L
  • 插入程式碼 Ctrl + K
  • 插入圖片 Ctrl + G
  • 提升標題 Ctrl + H
  • 有序列表 Ctrl + O
  • 無序列表 Ctrl + U
  • 橫線 Ctrl + R
  • 撤銷 Ctrl + Z
  • 重做 Ctrl + Y

Markdown及擴充套件

Markdown 是一種輕量級標記語言,它允許人們使用易讀易寫的純文字格式編寫文件,然後轉換成格式豐富的HTML頁面。 —— [ 維基百科 ]

使用簡單的符號標識不同的標題,將某些文字標記為粗體或者斜體,建立一個連結等,詳細語法參考幫助?。

本編輯器支援 Markdown Extra ,  擴充套件了很多好用的功能。具體請參考Github.

表格

Markdown Extra 表格語法:

專案 價格
Computer $1600
Phone $12
Pipe $1

可以使用冒號來定義對齊方式:

專案 價格 數量
Computer 1600 元 5
Phone 12 元 12
Pipe 1 元 234

定義列表

Markdown Extra 定義列表語法:
專案1
專案2
定義 A
定義 B
專案3
定義 C

定義 D

定義D內容

程式碼塊

程式碼塊語法遵循標準markdown程式碼,例如:

@requires_authorization
def somefunc(param1='', param2=0):
    '''A docstring'''
    if param1 > param2: # interesting
        print 'Greater'
    return (param2 - param1 + 1) or None
class SomeClass:
    pass
>>> message = '''interpreter
... prompt'''

腳註

生成一個腳註1.

目錄

[TOC]來生成目錄:

數學公式

  • 行內公式,數學公式為:Γ(n)=(n1)!nN
  • 塊級公式:
x=b±b24ac2a

更多LaTex語法請參考 這兒.

UML 圖:

可以渲染序列圖:

Created with Raphaël 2.1.0張三張三李四李四嘿,小四兒, 寫部落格了沒?李四愣了一下,說:忙得吐血,哪有時間寫。

或者流程圖:

Created with Raphaël 2.1.0開始我的操作確認?結束yesno
  • 關於 序列圖 語法,參考 這兒,
  • 關於 流程圖 語法,參考 這兒.

離線寫部落格

即使使用者在沒有網路的情況下,也可以通過本編輯器離線寫部落格(直接在曾經使用過的瀏覽器中輸入write.blog.csdn.net/mdeditor即可。Markdown編輯器使用瀏覽器離線儲存將內容儲存在本地。

使用者寫部落格的過程中,內容實時儲存在瀏覽器快取中,在使用者關閉瀏覽器或者其它異常情況下,內容不會丟失。使用者再次開啟瀏覽器時,會顯示上次使用者正在編輯的沒有發表的內容。

部落格發表後,本地快取將被刪除。 

使用者可以選擇 把正在寫的部落格儲存到伺服器草稿箱,即使換瀏覽器或者清除快取,內容也不會丟失。

注意:雖然瀏覽器儲存大部分時候都比較可靠,但為了您的資料安全,在聯網後,請務必及時發表或者儲存到伺服器草稿箱

瀏覽器相容

  1. 目前,本編輯器對Chrome瀏覽器支援最為完整。建議大家使用較新版本的Chrome。
  2. IE9以下不支援
  3. IE9,10,11存在以下問題
    1. 不支援離線功能
    2. IE9不支援檔案匯入匯出
    3. IE10不支援拖拽檔案匯入
  1. 這裡是 腳註內容.