android之自定義View和ViewGroup(一)(此篇不講述代碼,只講述原理和結構,帶你走進自定義的世界)

看了之前自己寫的兩個自定義View的博客,鑑於決定要好好寫博客,所以在此寫篇講述博客,因爲那兩篇自定義View的博客基本都是直接上代碼,很多新手肯定不知道爲什麼這麼寫,爲什麼是重寫onDraw之類的方法。

View就是視圖,你所能看見的控件都是直接或者間接繼承自它的,所謂的自定義View就是直接繼承View或者間接繼承(即繼承TextView之類的)然後重新它的相關方法來完成自己需要的樣子,自定義View是進階必須會的,記住是必須。你們可以去看看View的結構,裏面有很多方法,當然,我也不是大神,只是一個在那大神路上行走的一個菜B,所以咋們也沒必要完全弄明白View裏面的各個方法到底是幹嘛的,有什麼用,因爲即使大神也不一定都知道,咋們只需要知道哪些方法是拿來幹嘛的就夠了,94那麼雞汁~


自定義View需要知道的主要是這幾個方法:

1.onMeasure():改方法是用來測量View的大小的

2.onDraw():該方法是用來畫View的

這麼解釋,自定義View需要的步驟是,咋們需要先知道你需要畫的東西(View就是用canvas畫出來的)多大(在onMeasure中測量),然後才能開始用畫筆畫(畫這個操作是在onDraw方法中)。所以自定義View:先測量大小(重寫onMearsure()方法),再畫(重寫onDraw()方法)。


我們先來看重寫的onMeasure()方法,它的方法是這樣的:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

這個方法有兩個參數,widthMeasureSpec和heightMeasureSpec,Android系統有個類——MeasureSpec類,它裏面包含了測量模式和測量的大小,所以這兩個參數就是包含了寬和高的測量模式和測量大小,什麼是測量模式呢?就是測量大小的方式,說白點就是怎麼測大小,比如如果你設置了View的具體大小,那它就直接測View真實大小,如果設置View寬是match_parent,那麼它就會測你父View的大小,大概就是這麼個意思。測量好大小之後,我們在onMeasure方面裏通過setMeasuredDimension(int w,int h)方法來設置大小生效。

那麼具體怎麼測大小呢?我們就需要從widthMeasureSpec和heightMeasureSpec裏面提取測量模式和測量的大小了,可能細心點的人就會問了,尼瑪,你不是說了裏面包含了測量模式和測量的大小嗎,爲啥還要測量,喫飽了撐的啊,說實話,剛喫完午飯寫這篇博客,我現在還真沒喫飽~就特麼四季豆蓋飯,肉都不夠喫,好TM慘,咳,扯遠了,拉回來。爲啥還要測量呢?因爲裏面確實包含了測量的大小,但是不一樣,那個是系統幫我們測量的大小,不是我們自己測的,系統難道測不準?還要我們自己再測?那它有個屁用啊?不要急嘛,慢慢來呀,我給你一張紙,你給我畫一頭豬,畫呀,恩,當然你畫出來了,但是你特麼畫這麼大幹嘛?此時你就會說了:尼瑪,你又沒說具體畫多大,我咋知道要畫多大的。沒錯,就是這樣,你自定義一個View,比如設置了寬度100dp,好辦,系統一測很簡單100dp,但是你特麼給我來個wrap_content,我特麼怎麼知道具體是多大?但是此時系統還是會給你測,它不知道具體多大會給你默認測量大小爲match_parent的長度,很明顯不對啊,所以此時才需要自己測量了啊~懂了吧,還不懂?簡單,自己百度吧,啊哈哈。比如設置了寬度100dp或者wrap_content這些都可以理解爲測量模式。現在我們取出測量模式:

int wSpec = MeasureSpec.getMode(widthMeasureSpec);
int hSpec = MeasureSpec.getMode(heightMeasureSpec);
一個是寬的測量模式,一個是高的,測量模式有三個值:

1.EXACTLY:精確值模式,就是將寬高設爲具體值的時或者match_parent時,比如上面的100dp,我說了那麼系統測出來的就是跟我們這個值一樣。

2.AT_MOST:最大值模式,就是設置爲wrap_content時,根據內容的變化而變化,前提是不超過父控件給定的大小。

3.UNSPECIFIED:不定模式,就是不指定大小,View想多大就多大,基本只有自定義View纔會用到。

onMeasure()方法分析完了,就是這樣,所以我們需要根據不同的模式來進行測量View的大小,所以自定義View有測量大小這個步驟(在onMeasure()方法裏進行)。

我們再看看重寫的onDraw()方法:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
很簡單,畫布canvas一個參數,調用這個canvas進行繪畫就可以了,這個方法比較簡單,不做介紹了。


所以自定義View:重寫onMeasure()方法測量大小->在onDraw()方法裏畫出即可(比如TextView就是畫文字),本篇幅只做自定義View的講述和方法結構分析,所以就不寫案例了。之前有兩篇自定義View(自定義進度條)的博文,雖然有點粗糙,想看案例的可以去看看,詳細的自定義View案例會在後續博文中寫出。啊,對了,還有自定義ViewGroup的分析也會在後續博文中寫出。


補充:如果自定義View咋們是繼承已有的比如TextView或者Button之類的View來實現自定義View,那麼background,textsize之類的就不需要咋們自己定義了,因爲我們所繼承的View已經有了,除非不滿意需要自己更改;那麼如果直接自定義View繼承自View,那麼沒有所謂的background和textsize之類的屬性了,那麼此時就需要我們自定義了,那麼此時的步驟又是怎麼的呢?

1.在res/values文件夾下面新建文件夾attrs.xml,此文件用於自定義屬性比如背景色、字體大小等。

2.在我們自定義View的構造方法中獲取這些自定義的屬性並賦值給對應的屬性。

具體方法在後面的代碼篇中有涉及到~



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章