View體系

1.View簡(jiǎn)介

View是Android所有控件的基類,同時(shí)ViewGroup也是繼承自View。

從上圖可以發(fā)現(xiàn)我們常用的這些控件都是繼承于View。

2.Android坐標(biāo)系

Android中有兩種坐標(biāo)系,分別為Android坐標(biāo)系和視圖坐標(biāo)系。

在Android中,將屏幕的左上角的頂點(diǎn)作為Android坐標(biāo)系的原點(diǎn),這個(gè)原點(diǎn)向右是X軸正方向,原點(diǎn)向下是Y軸正方向。

MotionEvent提供的getRawX()和getRawY()獲取的坐標(biāo)都是Android坐標(biāo)系的坐標(biāo)。

3.視圖坐標(biāo)系


試圖坐標(biāo)系

View獲取自身寬高

getHeight():獲取View自身高度

getWidth():獲取View自身寬度

View自身坐標(biāo)

通過如下方法可以獲得View到其父控件(ViewGroup)的距離:

getTop():獲取View自身頂邊到其父布局頂邊的距離

getLeft():獲取View自身左邊到其父布局左邊的距離

getRight():獲取View自身右邊到其父布局左邊的距離

getBottom():獲取View自身底邊到其父布局頂邊的距離

MotionEvent提供的方法

MotionEvent也提供了各種獲取焦點(diǎn)坐標(biāo)的方法:

getX():獲取點(diǎn)擊事件距離控件左邊的距離,即視圖坐標(biāo)

getY():獲取點(diǎn)擊事件距離控件頂邊的距離,即視圖坐標(biāo)

getRawX():獲取點(diǎn)擊事件距離整個(gè)屏幕左邊距離,即絕對(duì)坐標(biāo)

getRawY():獲取點(diǎn)擊事件距離整個(gè)屏幕頂邊的的距離,即絕對(duì)坐標(biāo)

4.實(shí)現(xiàn)View滑動(dòng)的六種方法

ayout():

view進(jìn)行繪制的時(shí)候會(huì)調(diào)用onLayout()方法來設(shè)置顯示的位置,因此我們同樣也可以通過修改View的left、top、right、bottom這四種屬性來控制View的坐標(biāo)。

offsetLeftAndRight()與offsetTopAndBottom()

這兩種方法和layout()方法效果方法差不多,使用也差不多,我們將ACTION_MOVE中的代碼替換成如下代碼:


LayoutParams(改變布局參數(shù))

LayoutParams主要保存了一個(gè)View的布局參數(shù),因此我們可以通過LayoutParams來改變View的布局的參數(shù)從而達(dá)到了改變View的位置的效果。

動(dòng)畫

可以采用View動(dòng)畫來移動(dòng),在res目錄新建anim文件夾并創(chuàng)建translate.xml

scollTo與scollBy

scollTo(x,y)表示移動(dòng)到一個(gè)具體的坐標(biāo)點(diǎn),而scollBy(dx,dy)則表示移動(dòng)的增量為dx、dy。其中scollBy最終也是要調(diào)用scollTo的。scollTo、scollBy移動(dòng)的是View的內(nèi)容,如果在ViewGroup中使用則是移動(dòng)他所有的子View。

Scroller

我們用scollTo/scollBy方法來進(jìn)行滑動(dòng)時(shí),這個(gè)過程是瞬間完成的,所以用戶體驗(yàn)不大好。這里我們可以使用Scroller來實(shí)現(xiàn)有過度效果的滑動(dòng),這個(gè)過程不是瞬間完成的,而是在一定的時(shí)間間隔完成的。Scroller本身是不能實(shí)現(xiàn)View的滑動(dòng)的,它需要配合View的computeScroll()方法才能彈性滑動(dòng)的效果。

5.屬性動(dòng)畫


1.android視圖動(dòng)畫和屬性動(dòng)畫

2.android屬性動(dòng)畫

ObjectAnimator

ObjectAnimator是屬性動(dòng)畫最重要的類,創(chuàng)建一個(gè)ObjectAnimator只需通過他的靜態(tài)工廠類直接返還一個(gè)ObjectAnimator對(duì)象。參數(shù)包括一個(gè)對(duì)象和對(duì)象的屬性名字,但這個(gè)屬性必須有g(shù)et和set函數(shù),內(nèi)部會(huì)通過java反射機(jī)制來調(diào)用set函數(shù)修改對(duì)象的屬性值。

ValueAnimator

ValueAnimator不提供任何動(dòng)畫效果,它更像一個(gè)數(shù)值發(fā)生器,用來產(chǎn)生一定規(guī)律數(shù)字,從而讓調(diào)用者來控制動(dòng)畫的實(shí)現(xiàn)過程。

動(dòng)畫的監(jiān)聽

完整的動(dòng)畫具有start,Repeat,End,Cancel四個(gè)過程:

組合動(dòng)畫-AnimatorSet

這個(gè)類提供了一個(gè)play()方法,如果我們向這個(gè)方法中傳入一個(gè)Animator對(duì)象(ValueAnimator或ObjectAnimator)將會(huì)返回一個(gè)AnimatorSet.Builder的實(shí)例,AnimatorSet.Builder中包括以下四個(gè)方法:

after(Animator anim) 將現(xiàn)有動(dòng)畫插入到傳入的動(dòng)畫之后執(zhí)行

after(long delay) 將現(xiàn)有動(dòng)畫延遲指定毫秒后執(zhí)行

before(Animator anim) 將現(xiàn)有動(dòng)畫插入到傳入的動(dòng)畫之前執(zhí)行

with(Animator anim) 將現(xiàn)有動(dòng)畫和傳入的動(dòng)畫同時(shí)執(zhí)行

組合動(dòng)畫-PropertyValuesHolder

除了上面AnimatorSet類還可以使用PropertyValuesHolder類來實(shí)現(xiàn)組合動(dòng)畫,不過這個(gè)組合動(dòng)畫就沒有上面的豐富了,使用PropertyValuesHolder類只能多個(gè)動(dòng)畫一起執(zhí)行。當(dāng)然我們得結(jié)合 ObjectAnimator.ofPropertyValuesHolder(Object target,

PropertyValuesHolder… values);方法來使用。

xml中使用屬性動(dòng)畫

和視圖動(dòng)畫一樣,屬性動(dòng)畫也可以直接寫在xml中:

在res文件中新建animator文件。

6.從源碼解析Scroller

1.Scroller的構(gòu)造函數(shù)

要想使用Scroller,必須先調(diào)用new Scroller()

2.Scroller的startScroll方法

3.Scroller的computeScrollOffset方法

7.從源碼解析View的事件分發(fā)機(jī)制

1.處理點(diǎn)擊事件的方法

View的層級(jí)

我們知道View的結(jié)構(gòu)是樹形的結(jié)構(gòu),View可以放在ViewGroup中,這個(gè)ViewGroup也可以放到另一個(gè)ViewGroup中,這樣層層的嵌套就組成了View的層級(jí)。

什么是點(diǎn)擊事件分發(fā)

當(dāng)我們點(diǎn)擊屏幕,就產(chǎn)生了觸摸事件,這個(gè)事件被封裝成了一個(gè)類:MotionEvent。而當(dāng)這個(gè)MotionEvent產(chǎn)生后,那么系統(tǒng)就會(huì)將這個(gè)MotionEvent傳遞給View的層級(jí),MotionEvent在View的層級(jí)傳遞的過程就是點(diǎn)擊事件分發(fā)。

點(diǎn)擊事件分發(fā)的重要方法

點(diǎn)擊事件有三個(gè)重要的方法它們分別是:

dispatchTouchEvent(MotionEvent ev):用來進(jìn)行事件的分發(fā)

onInterceptTouchEvent(MotionEvent ev):用來進(jìn)行事件的攔截,在dispatchTouchEvent()中調(diào)用,需要注意的是View沒有提供該方法

onTouchEvent(MotionEvent ev):用來處理點(diǎn)擊事件,在dispatchTouchEvent()方法中進(jìn)行調(diào)用

2.點(diǎn)擊事件分發(fā)的傳遞規(guī)則

看到這里我們就可以知道點(diǎn)擊事件分發(fā)的這三個(gè)重要方法的關(guān)系,用偽代碼來簡(jiǎn)單表示就是:


8.從源碼解析Activity的構(gòu)成

1.從源碼解析Activity的構(gòu)成

2.圖解Activity的構(gòu)成


9.源碼解析View的measure流程

1.View的measure流程

先來看看onMeasure()方法(View.java):

看看setMeasuredDimension()方法:

2.ViewGroup的measure流程

ViewGroup的measure原理

講完了View的measure流程,接下來看看ViewGroup的measure流程,對(duì)于ViewGroup,它不只要measure自己本身,還要遍歷的調(diào)用子元素的measure()方法,ViewGroup中沒有定義onMeasure()方法,但他定義了measureChildren()方法(ViewGroup.java)。


LinearLayout的measure流程

ViewGroup并沒有提供onMeasure()方法,而是讓其子類來各自實(shí)現(xiàn)測(cè)量的方法,究其原因就是ViewGroup有不同的布局的需要很難統(tǒng)一。


10.從源碼解析View的layout和draw流程

1.View的layout流程

2.View的draw流程

11.自定義View

1.自定義View簡(jiǎn)介

自定義View按照筆者的劃分,分為兩大類,一種是自定義View,一種是自定義ViewGroup;其中自定義View又分為繼承View和繼承系統(tǒng)控件兩種。這篇文章首先先了解下兩大類的其中一種:自定義View。

2.繼承系統(tǒng)控件的自定義View

這種自定義View在系統(tǒng)控件的基礎(chǔ)上進(jìn)行拓展,一般是添加新的功能或者修改顯示的效果,一般情況下我們?cè)趏nDraw()方法中進(jìn)行處理。

3.繼承View的自定義View

與上面的繼承系統(tǒng)控件的自定義View不同,繼承View的自定義View實(shí)現(xiàn)起來要稍微復(fù)雜一些,不只是要實(shí)現(xiàn)onDraw()方法,而且在實(shí)現(xiàn)過程中還要考慮到wrap_content屬性以及padding屬性的設(shè)置;為了方便配置自己的自定義View還會(huì)對(duì)外提供自定義的屬性,另外如果要改變觸控的邏輯,還要重寫onTouchEvent()等觸控事件的方法。

最后編輯于
?著作權(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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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