2018-07-13

Android 自定義View

前言

首先我們先了解一下,什么叫view?Android官方文檔對(duì)View的解釋是這樣的:表示用戶(hù)界面組件的基本構(gòu)建塊,視圖占據(jù)屏幕上的矩形區(qū)域,負(fù)責(zé)繪圖和事件處理。以上可以看出view是程序與用戶(hù)之間進(jìn)行交互的橋梁。view的形狀,大小,表現(xiàn)形式多種多樣,所有就會(huì)發(fā)現(xiàn)Android系統(tǒng)能提供給我們的有時(shí)候并不能滿(mǎn)足我們的需求,所以就會(huì)需要程序員去自定義view。

下面我就介紹以下如何自定義view,我將自定義View基礎(chǔ)、自定義View繪制流程、事件分發(fā)機(jī)制這三個(gè)方面來(lái)介紹。

一 自定義View基礎(chǔ)

1.1 坐標(biāo)系

屏幕坐標(biāo)系與數(shù)學(xué)坐標(biāo)系的差異

1.1.1 屏幕坐標(biāo)系

1.1.1 view的坐標(biāo)系

注意:View的坐標(biāo)系都是相對(duì)于父控件而言。

1.2 顏色

三原色

1.3 分類(lèi)

根據(jù)用途來(lái)分,一般將自定義分為兩種:即自定義控件和自定義布局.

1.4 自定義屬性

自定義屬性步驟

二 自定義view繪制流程

2.1 繪制流程

2.2 相關(guān)函數(shù)介紹

2.2.1 構(gòu)造函數(shù)

一個(gè)參的構(gòu)造,一般在java代碼中直接new一個(gè)View時(shí)調(diào)用。

兩個(gè)參的構(gòu)造,一般在Layout文件中使用的時(shí)候調(diào)用,關(guān)于它的所有屬性(包括自定義屬性)都會(huì)通過(guò)attrs傳遞進(jìn)來(lái)。

三個(gè)參數(shù)的構(gòu)造,第三個(gè)參數(shù)是默認(rèn)的Style,這里的默認(rèn)的Style是指它在當(dāng)前Application或Activity所用的Theme中的默認(rèn)Style。

四個(gè)參數(shù)的構(gòu)造,第四個(gè)參數(shù)是指向一個(gè)style的ID,但是是在defStyleAttr為0,或者defStyle不為0,但theme沒(méi)有為defStyleAttr屬性賦值時(shí)起作用。

2.2.2 測(cè)量view的大小函數(shù)-onMeasure()

作用:測(cè)量View的大小,并從widthMeasureSpec 和 heightMeasureSpec中取出寬高的相關(guān)數(shù)據(jù),它們其實(shí)不是寬和高, 而是由寬、高和各自方向上對(duì)應(yīng)的測(cè)量模式來(lái)合成的一個(gè)值。

測(cè)量模式:

三種測(cè)量模式,通過(guò)MeasureSpec.getMode()得到測(cè)量模式, Measure.getSize()得到測(cè)量數(shù)值。

2.2.3 確定view的大小函數(shù)-onSizeChanged()

作用:確定View大小,在視圖大小發(fā)生改變時(shí)調(diào)用,它有四個(gè)參數(shù),分別為寬度,高度,上一次寬度,上一次高度。

2.2.4 確定子view的布局-onLayout()

作用:它用于確定子View的位置,在自定義ViewGroup中會(huì)用到,他調(diào)用的是子View的layout函數(shù)。它有四個(gè)參數(shù)如下:

2.2.5 繪制view的函數(shù)-onDraw()

作用:繪制內(nèi)容,使用canvas進(jìn)行繪圖.

三 事件分發(fā)機(jī)制

為什么要有事件分發(fā)機(jī)制?

有時(shí)候界面上的view并不是很規(guī)則整齊的排列在一起,View之間是有可能重疊在一起的,當(dāng)我們點(diǎn)擊的地方有多個(gè)View響應(yīng)時(shí),這個(gè)點(diǎn)擊事件應(yīng)該分發(fā)給誰(shuí)?為了解決這一部分就有了事件分發(fā)機(jī)制。

3.1 事件分發(fā)核心函數(shù)

以上三個(gè)方法都有一個(gè)boolean類(lèi)型的返回值,通過(guò)返回true或者false來(lái)控制事件的流程.

3.2 事件分發(fā)流程

責(zé)任鏈模式,即如果自己能處理就攔截下來(lái)自己處理,如果不能處理或者不確定就交給責(zé)任鏈中的下一個(gè)對(duì)象。如下圖:

3.2.1 事件分發(fā)機(jī)制流程詳解

事件傳遞順序:

注意:事件傳遞過(guò)程先執(zhí)行分發(fā),再執(zhí)行攔截,事件傳遞返回 true,表示事件被攔截,交給自己的onTouchEvent處理;false,表示不攔截,向下傳遞。

事件處理順序:

注意:事件的處理都要進(jìn)過(guò)onTouchEvent,事件處理返回true,表示事件自己處理,false,表示向上傳遞。

3.2.2 事件分發(fā)機(jī)制流程概括

(1)事件如果被消費(fèi),就意味著事件傳遞消息被終止。

(2)如果事件一直沒(méi)有被消費(fèi)就會(huì)傳遞給activity,如果activity也不需要就會(huì)被拋棄。

(3)判斷事件是否被消費(fèi)是根據(jù)返回值,并不是根據(jù)你是否使用了該事件。

Android 事件分發(fā),一般可以理解為:

(a)ViewGroup對(duì)點(diǎn)擊事件的分發(fā)機(jī)制。

(b)View對(duì)點(diǎn)擊事件的分發(fā)機(jī)制。

3.3 MotionEvent對(duì)象

根據(jù)面向?qū)ο蟮乃枷?,事件被封裝成MotionEvent對(duì)象。

對(duì)于單指觸控來(lái)說(shuō),一次簡(jiǎn)單的交互流程是:

3.4 ViewGroup的事件分發(fā)

注意:ViewGroup的事件分發(fā)不僅要考慮自身,還要考慮子View.

ViewGroup的分發(fā)流程:

3.4.1 子view存在重合點(diǎn)時(shí)的處理

情況一:

只有View1可以點(diǎn)擊時(shí),該點(diǎn)擊事件分配給View1

情況二:

只有View2可以點(diǎn)擊時(shí),該點(diǎn)擊事件分配給View2

情況三:

View1、View2均可點(diǎn)擊時(shí),該點(diǎn)擊事件分配給View2,如果View2將事件消費(fèi)掉了,則View1將接收不到.

3.4.2 view的可點(diǎn)擊情況分類(lèi):

onClick

onLongClick

onContextClick

android:clickable=“true”

button ,ImageButton,CheckBox默認(rèn)是可點(diǎn)擊的。

3.5 view的事件分發(fā)流程

3.6 總結(jié)

以上只是個(gè)人對(duì)自定義view的理解.有不對(duì)的地方,歡迎指正!

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

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

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