Android自定義View(一)

在項目開發(fā)之中,當android原生的view不能滿足我們的需求的時候,我們往往都是通過自定義view去重新繪制出符合的view,其實自定義view說難不難,說容易也不容易,本篇文章是我自己在學(xué)習(xí)自定義view的時候總結(jié)的一些內(nèi)容


步驟:

1.在res/values下創(chuàng)建一個attrs.xml,用來存放我們的屬性(名字可以隨便取,但最好就是規(guī)范)
2.在構(gòu)造方法里,獲取屬性并且賦值
3.繼承view,并且重寫onMeasure(),onDraw()方法
4.在布局文件中,包名+類名引入view使用

注意事項:

1.最好實現(xiàn)3個構(gòu)造方法,為了擴展
2.如果有跟用戶交互的功能或者防止跟其他view發(fā)生事件沖突的時候,需要做onTonchEvent處理
3.最好適應(yīng)view的三種測量模式,AT_MOST,EXACTLY,UNSPECIFIED,如果你這個view是固定寬高的話,那可以考慮不做適應(yīng)
4.在布局文件中,記得是包名+類名,并且如果有自定義屬性的話,需要加上命名空間

onMeasure

該方法是測量該view的在布局中的大小,有三種模式,AT_MOST,EXACTLY,UNSPECIFIED

EXACTLY

是指當我們?yōu)関iew設(shè)定了明確的值所對應(yīng)的模式,如100dp,match_parent(該值是指view占滿全屏,相當于屏幕的值,所以是個明確值)

AT_MOST

意思是說最多不能超過某個值,如wrap_content,當設(shè)置了wrap_content時,意味著說,這個view是由內(nèi)容去決定大小,假如是個textview,那么它可能由字體去決定大小,那么這個字體會有個大小,則說這個view的大小不能超過這個字體的大小,假如該view被包裹在一個父控件中,則說這個view不能超過父空間的大小

UNSPECIFIED

這個模式是說我沒有限制view的大小,你愛多大就多大,多小就多小,這種模式多數(shù)出現(xiàn)在listview,recyclerview,ScrollView等可以隨意改變itemview的大小的控件中,這里控件的itemview是不規(guī)則的,例如listview中某個view高點,某個小點,recyclerview多item布局的不規(guī)則布局等都是這種模式

onDraw

這方法就是將view繪制出來,好了,說了差不多了,開始把,根據(jù)步驟開始


attrs.xml文件:

attrs.xml

很簡單,就一個背景的屬性,format的意思是說應(yīng)該用取值類型,有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag,這里對幾個不熟悉的介紹下:

1.demension:尺寸,相當于文字的大小

如: <attr name="titleTextSize" format="dimension" /> ,使用的時候就可以 android:textSize = "42sp"


2.reference:參照某個資源ID

如<attr name = "background" format = "reference" /> ,布局文件就可以這樣使用:android:background = "@drawable/圖片ID"


3.fraction:百分數(shù)

如<attr name = "pivotX" format = "fraction" /> ,使用的時候可以這樣 android:pivotX = "200%"


4.enum:枚舉值,這個值在定義屬性的時候比較特殊點,要這樣寫

<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr> ,使用的時候這樣
<LinearLayout
android:orientation = "vertical或horizontal"

android:layout_width = "fill_parent"
android:layout_height = "fill_parent" />


自定義view


一個最簡單的view就寫好了,這里先不寫onMeasure方法,我們總的流程就是,繼承view之后,通過obtainStyledAttributes()這個方法獲取到屬性表,并且獲得屬性之后賦值給我們的paint,然后通過canvas去繪制出我們的view,最后別忘了,在布局文件中引入


效果圖

我們還可以設(shè)置它的背景,首先需要引入我們的命名空間
xmlns:app="http://schemas.android.com/apk/res-auto"
然后調(diào)用屬性


初步的view已經(jīng)寫好了,但就這樣完事了嗎?然而并沒有,前面說過,自定義view是需要重寫onMeasure方法的,如果沒用,假如我們現(xiàn)在去設(shè)置android:padding屬性,你會發(fā)現(xiàn),它根本沒有任何變化,為什么呢?因為這就是我們并沒有對它的模式進行處理,也就是說,其實它的warp_content和match_parent是一樣的,好了,現(xiàn)在我們就處理下


首先是對padding的處理,這個還是挺簡單的,當我們設(shè)置了它的padding之后,我們就用它的寬高減去padding就可以了

效果圖

這里設(shè)置了android:padding="20dp"


現(xiàn)在我們來重寫onMeasure方法,我們先想下,我們在布局文件設(shè)定view的時候,會有多少種寫法呢?一種是寬高都是warp_content,一種是寬高都是match_parent,一種是寬是warp_content高是match_parent,反之一樣,一種寬高都是指定值,一種是寬或者高給定值,另外一個是warp_content或者match_parent,其實這么多種之中,有幾種是重復(fù)利用的,就是當寬高其中之一指定值,另外一個是match_parent,或者是兩者都是match_parent,前面說了,這種都是相當于給了明確值,都是EXACTLY模式,其實onMeasure方法主要的是針對AT_MOST做處理,那么這樣就好辦了


首先獲取到測量模式以及測量值


然后就是一系列的判斷了


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容