android自定義控制項的常用方法

2021-07-25 10:19:41 字數 4322 閱讀 1361



inflate方法常常用來解析乙個

xml布局檔案,在自定義組合式控制項中常常使用,使用的姿勢包括:

view.inflate(context, resource, root)

layoutinflater.from(getcontext()).inflate(resource, root);

而view.inflate其實還是呼叫的

layoutinflater

去解析乙個

xml:

public static view inflate(context context, int resource, viewgroup root)

所以這兩種姿勢沒啥區別,這裡來討論一下inflate(resouce, root)的返回值,引數

resource

是布局資源,

root

是傳入的乙個根節點。如果

root

傳入乙個

null

,inflate

就會解析

resource

對應的xml

,返回這個

xml中的根節點,如果

root

傳入不為

null

,inflate

會解析這個

xml布局並且新增到根節點

root

下,然後返回根節點

root

。另外還有帶三個引數的inflate方法:

inflate(

intresource, viewgroup root,

boolean

attachtoroot)

這裡多了乙個引數attachtoroot,如果

root

為null

,則返回解析後的

xml布局中的根節點;如果

root

不為null,attachtoroot

為true,inflate

會解析這個

xml布局並且新增到根節點

root

下,然後返回根節點

root

;如果root

不為null,attachtoroot

為false,inflate

會解析這個

xml布局但不會新增到根節點

root

下,然後返回解析後的

xml布局中的根節點,這時候

root

的作用只是為

xml中的根節點提供布局引數的屬性,因為

xml中的根節點不知道自己的父容器是誰,所以如果沒有人給它提供的話,它的布局引數就會失效。

onfinishinflate是當所有的孩子都解析完後的乙個呼叫。比如我們自定義乙個

viewgroup

,想要去找到孩子做一些設定,這時候如果在自定義

viewgroup

的建構函式去

findviewbyid

的話,會返回乙個

null,

因為此時孩子還沒有解析好,也就是還沒有生出來。這時候我們可以去覆寫

onfinishinflate

,當孩子解析好後再去

find

。關於requestlayout的介紹比較多,

requestlayout()

方法會觸發

measure

過程和layout

過程,不會呼叫

draw

過程,也不會重新繪製任何

view

包括該呼叫者本身

onsizechange是控制項的大小發生變化的時候的呼叫,它的呼叫軌跡是

layout->setframe->sizechange->onsizechange

。當控制項第一次布局時肯定會被呼叫到,我們覆寫該方法可以獲取到控制項的大小。所以這個方法通常被用來在裡面初始化跟控制項大小相關的成員變數。

invalidate使用的非常頻繁,它會觸發

view

的重新繪製,也就是繪製流程的

draw

過程,但不會呼叫測量和布局過程

我們都知道android的

ui是單執行緒模型,只能在主線程更新

ui,所以我們只能在主線程呼叫

invalidate,

如果想要在子執行緒更新

ui,可以使用

handler

傳送乙個

msg到主線程,然後在處理

msg的時候去呼叫

invalidate

。另外,我們可以直接呼叫

postinvalidate

去在子執行緒更新ui,

postinvalidate

內部實現也是使用

handler

來做傳送

msg到主線程然後呼叫

invalidate

。自定義viewgroup通常是不會去繪製自己的,如果大家重寫

viewgroup

裡面的draw

方法或者

ondraw

方法會發現它們根本就不會被呼叫到。但是如果給你的

viewgroup

設定乙個背景,就會發現

draw

方法和ondraw

方法又都會走了。

我們知道viewgroup本身是乙個

view,

它的繪製是被其父容器發起的,具體的位置是在

viewgroup

中的drawchild

方法:protected boolean drawchild(canvas canvas, view child, long drawingtime)

注意這裡的draw方法是帶三個引數的,與我們通常講的帶乙個引數的

draw

方法不一樣。在

view

類中找到帶三個引數的

draw

方法,發現裡面有這麼一段**:

if(!hasdisplaylist)

else }

從這裡我們可以看出一點端倪,通常乙個viewgroup預設是會跳過繪製的,也即

(mprivateflags & pflag_skip_draw) == pflag_skip_draw

會返回乙個

true,

那麼會直接走

dispatchdraw

方法去畫它自己的孩子去了,並不會呼叫帶乙個引數的

draw(canvas) ,

但是當這個

viewgroup

有背景或者

setwillnotdraw(false)

是,就會走

draw(canvas)

方法。所以如果我們自定義乙個viewgroup並且想要實現它本身的繪製的話,就可以給它設定乙個背景或者呼叫

setwillnotdraw(false)

onattachedtowindow是當乙個

view

繫結到window

上時的呼叫,根據

view

類裡面的對這個方法的注釋,

onattachedtowindow

肯定會在

ondraw

方法之前呼叫。

在自定義控制項裡面,我們可以在onattachedtowindow註冊一些廣播接收器,觀察者或者開啟一些任務,大家可以參考

textclock

的裡面的實現。

ondetachedfromwindow對應於

onattachedtowindow,

是當乙個

view

從window

上移除時的乙個呼叫。如果在

onattachedwindow

裡面註冊了一些監聽,那麼通常就要在

ondetachedfromwindow

裡面反註冊。

viewtreeobserver是檢視樹的觀察者,監聽一些檢視樹的全域性變化,這些全域性變化包括整個檢視樹的布局,開始繪製,觸控模式的變化等。我們不能直接初始化

viewtreeobserver

的物件,需要通過

getviewtreeobserver()

去獲取。

當在乙個檢視樹中全域性布局發生改變或者檢視樹中的某個檢視的可視狀態發生改變的***,一般的使用姿勢是:

getviewtreeobserver().addongloballayoutlistener(

newongloballayoutlistener()

});當乙個檢視樹將要繪製時的***,一般的使用姿勢是:

getviewtreeobserver().addonpredrawlistener(

newonpredrawlistener()

});

Android 自定義控制項

幹android也有一段的時間了,自定義這塊的東西覺得還是很有比較複習一下基礎的東西。自定義控制項和自定義元件基本上的使用都是在專案中基本的android控制項滿足不了需求的時候使用的。所以,如果要高出特別炫的特效,或者比較特殊的控制項排列方式,例如瀑布流,那麼就要好好學學自定義咯。首先,先簡單的介...

android自定義控制項

android自定義控制項 二 入門,繼承view 說說android 兩種為自定義元件新增屬性的使用方法和區別 自定義控制項的屬性 自定義控制項 今天花了3,4個小時看了自定義控制項,看 懂了,還沒有實踐,因為時間不夠,日後實踐。總結下 自定義控制項有3種方式 繼承已有控制項 繼承乙個容器控制項,...

Android自定義控制項

android學習筆記,整理給自己複習的時候看的,謝謝!1.自定義開關 1.宣告介面物件 public inte ce onswitchstateupdatelistener 2.新增設定介面物件的方法,外部進行呼叫 public void setonswitchstateupdatelistene...