【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】教你五分鐘實(shí)現(xiàn)Android超漂亮的刻度輪播控件實(shí)例教程_第1頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】教你五分鐘實(shí)現(xiàn)Android超漂亮的刻度輪播控件實(shí)例教程_第2頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】教你五分鐘實(shí)現(xiàn)Android超漂亮的刻度輪播控件實(shí)例教程_第3頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】教你五分鐘實(shí)現(xiàn)Android超漂亮的刻度輪播控件實(shí)例教程_第4頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】教你五分鐘實(shí)現(xiàn)Android超漂亮的刻度輪播控件實(shí)例教程_第5頁(yè)
免費(fèi)預(yù)覽已結(jié)束,剩余2頁(yè)可下載查看

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】教你五分鐘實(shí)現(xiàn)Android超漂亮的刻度輪播控件實(shí)例教程

前言最近一直在做音視頻的工作,已經(jīng)有大半年沒(méi)有寫應(yīng)用層的東西了,生怕越來(lái)越生疏。正好前段時(shí)間接了個(gè)外包項(xiàng)目,才得以回顧一下。項(xiàng)目中有一個(gè)控件挺簡(jiǎn)潔漂亮的,而且用到的技術(shù)也比較基礎(chǔ),比較適合新手學(xué)習(xí),所以單獨(dú)開(kāi)源出來(lái),希望能對(duì)初學(xué)者有所幫助。

截圖

截屏

一、自定義View的常用方法

相信每個(gè)Android程序員都知道,我們每天的開(kāi)發(fā)工作當(dāng)中都在不停地跟View打交道,Android中的任何一個(gè)布局、任何一個(gè)控件其實(shí)都是直接或間接繼承自View的,如TextView、Button、ImageView、ListView等。一些接觸Android不久的朋友對(duì)自定義View都有一絲畏懼感,總感覺(jué)這是一個(gè)比較高級(jí)的技術(shù),但其實(shí)自定義View并不復(fù)雜,有時(shí)候只需要簡(jiǎn)單幾行代碼就可以完成了。說(shuō)到自定義View,總繞不開(kāi)下面幾個(gè)方法1.overridefunonMeasure(widthMeasureSpec:Int,heightMeasureSpec:Int)

??初始化View時(shí),用于測(cè)量大小,并對(duì)View的大小進(jìn)行控制,比如可以控制View的寬高比例。2.overridefunonDraw(canvas:Canvas)

??View的繪制回調(diào),所有的畫筆、畫布操作都在這里。切勿在此方法進(jìn)行耗時(shí)操作,能在外部計(jì)算的都在外部計(jì)算,并且盡量不要在這里初始化變量。因?yàn)檎G闆r下這個(gè)方法會(huì)以60fps的速度進(jìn)行回調(diào),如果有耗時(shí)操作,將會(huì)卡頓,如果初始化大量對(duì)象,則會(huì)消耗大量?jī)?nèi)存??傊?,跟畫布無(wú)關(guān)的操作都不要寫在這里。3.invalidate()

??用于通知View進(jìn)行重繪,也就是重新調(diào)用onDraw,當(dāng)我們界面屬性發(fā)生變化時(shí),就可以調(diào)用該方法來(lái)進(jìn)行重繪,而不是調(diào)用onDraw,這個(gè)方法非常常用。4.overridefunonTouchEvent(event:MotionEvent):Boolean

??相信大家都知道,這個(gè)是觸摸事件回調(diào)。在這里可以處理一些手勢(shì)操作。二、自定義一個(gè)刻度控件RulerView

??由于代碼比較多,而且源碼里面的注釋也比較詳細(xì),所以這里只挑重點(diǎn)的幾個(gè)方法講解一下。如果有問(wèn)題,或者錯(cuò)誤,歡迎在評(píng)論區(qū)留言。

??觀察本文開(kāi)始的視頻,我們可以發(fā)現(xiàn),該控件雖然看起來(lái)挺簡(jiǎn)潔,但是需要控制的部分卻不少,光刻度就有三種類型,還有一些文字。

普通刻度,寬度比較短,顏色比較淺,不帶文字。

整10刻度,寬度比較長(zhǎng),顏色相較普通刻度深一點(diǎn),并且?guī)в形淖帧?/p>

游標(biāo)刻度,寬度在三類刻度里面是最長(zhǎng)的,顏色高亮,并且也帶有文字。

標(biāo)簽文字,用于描述該刻度的用途。

普通刻度,寬度比較短,顏色比較淺,不帶文字。

整10刻度,寬度比較長(zhǎng),顏色相較普通刻度深一點(diǎn),并且?guī)в形淖帧?/p>

游標(biāo)刻度,寬度在三類刻度里面是最長(zhǎng)的,顏色高亮,并且也帶有文字。

標(biāo)簽文字,用于描述該刻度的用途。

??以上都是需要我們用畫筆來(lái)繪制的,所以我們定義了以下幾個(gè)畫筆,為了避免在onDraw中頻繁更改畫筆屬性,這里又對(duì)文字和刻度定義了單獨(dú)的畫筆,目的是避免任何畫筆屬性的改變和在onDraw中改變屬性導(dǎo)致繪制過(guò)于耗時(shí),更重要的是來(lái)回更改畫筆的屬性過(guò)于復(fù)雜,不便于操作和問(wèn)題排查。

scalePaint:Paint//刻度畫筆

scalePointerPaint:Paint//整10刻度文字畫筆

scalePointerTextPaint:Paint//整10刻度文字畫筆

cursorPaint:Paint//游標(biāo)畫筆

cursorTextPaint:Paint//游標(biāo)文字畫筆

cursorLabelPaint:Paint//標(biāo)簽文字畫筆

scalePaint:Paint//刻度畫筆

scalePointerPaint:Paint//整10刻度文字畫筆

scalePointerTextPaint:Paint//整10刻度文字畫筆

cursorPaint:Paint//游標(biāo)畫筆

cursorTextPaint:Paint//游標(biāo)文字畫筆

cursorLabelPaint:Paint//標(biāo)簽文字畫筆

1、從xml設(shè)置的屬性初始化參數(shù)

??除了基礎(chǔ)的畫筆對(duì)象,還需要一些畫筆必要的屬性,比如我們繪制一個(gè)刻度,需要知道刻度位置、大小和間距。所以圍繞這些,又定義了一系列屬性。這些屬性可以由xml定義時(shí)提供,由此引出View的另一個(gè)重要用法。

??這個(gè)用法比較固定,都是這個(gè)套路。其中需要注意的是,類似于R.styleable.app_scaleWidth這種id是在values/attrs.xml中定義的,app代表命名空間,可以自定義,scaleWidth就是屬性id,跟layout_width這些是一樣的。我們?cè)谝粋€(gè)命名空間中定義了一個(gè)屬性id后,就可以像使用layout_width和layout_height那樣從xml中向View傳遞屬性了。此時(shí)在View的構(gòu)造方法中可以直接獲取這些屬性值,代碼如下。2、繪制View

??本文并沒(méi)有使用View提供的scrollTo和scrollBy來(lái)控制滾動(dòng),而是重新定義一個(gè)x,y屬性來(lái)記錄滾動(dòng)位置,通過(guò)這個(gè)屬性繪制相應(yīng)的位置,來(lái)實(shí)現(xiàn)滾動(dòng)效果。這樣操作可以通過(guò)指定繪制區(qū)域(屏幕外的內(nèi)容不繪制,感興趣的同學(xué)可以去嘗試實(shí)現(xiàn))來(lái)解決性能問(wèn)題。

??drawScale通過(guò)遍歷items來(lái)繪制每一個(gè)元素,包括刻度和對(duì)應(yīng)的文字,都是比較基本的操作。需要注意的是canvas.drawText默認(rèn)情況下的x,y是指文字的左下角位置。3、支持滾動(dòng)

??Android的手勢(shì)滾動(dòng)操作比較簡(jiǎn)單,不需要自己去實(shí)現(xiàn)各種邏輯控制,而是通過(guò)系統(tǒng)提供的Scroller來(lái)計(jì)算滾動(dòng)位置。

??首先我們需要一個(gè)GestureDetectorCompat和OverScroller,前者用于手勢(shì)監(jiān)聽(tīng),后者通過(guò)MotionEvent來(lái)計(jì)算滾動(dòng)位置。

1.mGestureDetector:GestureDetectorCompat

2.scroller:OverScroller

1.mGestureDetector:GestureDetectorCompat2.scroller:OverScroller

??構(gòu)造一個(gè)GestureDetectorCompat對(duì)象,需要先提供一個(gè)OnGestureListener,用來(lái)監(jiān)聽(tīng)onScroll和onFling事件。其實(shí)就是MotionEvent經(jīng)過(guò)GestureDetectorCompat處理之后,就變成了可以直接使用的滾動(dòng)和慣性滾動(dòng)事件,然后通過(guò)這兩個(gè)回調(diào)通知我們。

??在onScroll中,我們通過(guò)橫向和縱向滾動(dòng)距離來(lái)計(jì)算滾動(dòng)方向,如果橫向滾動(dòng)距離大于縱向滾動(dòng)距離,我們則可以認(rèn)為是橫向滾動(dòng),反之則是縱向滾動(dòng)。本文只需要縱向滾動(dòng)。

??拿到滾動(dòng)方向之后,我們就可以對(duì)滾動(dòng)位置x,y進(jìn)行累加,記錄每一次滑動(dòng)之后的新的位置。最后通過(guò)postInvalidateOnAnimation或invalidate來(lái)通知重新繪制,onDraw根據(jù)新的x,y繪制對(duì)應(yīng)位置的畫面,來(lái)實(shí)現(xiàn)滑動(dòng)。

??雖然通過(guò)onScroll已經(jīng)實(shí)現(xiàn)了View的滑動(dòng),但只是實(shí)現(xiàn)跟隨手指運(yùn)動(dòng),還沒(méi)有實(shí)現(xiàn)“拋”的動(dòng)作。在現(xiàn)實(shí)世界中,運(yùn)動(dòng)是有慣性的,如果只實(shí)現(xiàn)onScroll,一切都顯得很生硬。那么如何實(shí)現(xiàn)慣性運(yùn)動(dòng)呢,我們自己計(jì)算?想想都可怕,這么多運(yùn)動(dòng)函數(shù),相信不是一般人能應(yīng)付的來(lái)的。幸運(yùn)的是,這個(gè)計(jì)算我們可以交給GestureDetectorCompat的onFling。

??onFling有四個(gè)參數(shù),前兩個(gè)是MotionEvent,分別代表前后兩個(gè)觸摸事件。velocityX:Float代表X軸滾動(dòng)速率,velocityY:Float代表Y軸滾動(dòng)速率,我們不需要關(guān)心這兩個(gè)值如何,直接交給scroller處理即可。

??這里也許有人要問(wèn)了,我們的手指離開(kāi)屏幕之后便不再產(chǎn)生事件,View是如何實(shí)現(xiàn)持續(xù)滑動(dòng)的呢。再回頭看一下onFling回調(diào)也確實(shí)如此,onFling只會(huì)根據(jù)手指離開(kāi)屏幕前兩個(gè)MotionEvent來(lái)計(jì)算速率,之后就再也沒(méi)有回調(diào),所以scroller.fling也僅僅是調(diào)用了一次,并不能持續(xù)滾動(dòng)。那我們?nèi)绾螌?shí)現(xiàn)持續(xù)的慣性滾動(dòng)呢?

??要實(shí)現(xiàn)持續(xù)的慣性滾動(dòng),就得依賴于overridefuncomputeScroll(),該方法由draw過(guò)程中調(diào)用,我們可以通過(guò)invalidate->onDraw->computeScroll->invalidate這樣一個(gè)循環(huán)來(lái)控制慣性滾動(dòng),直至慣性滾動(dòng)停止,具體實(shí)現(xiàn)可以參考文章最后的源碼。??至此自定義View的繪制和事件兩個(gè)重要部分都講完了。喜歡的話記得點(diǎn)贊、評(píng)論和關(guān)注,您的關(guān)注是我的鼓勵(lì)。文章最后貼出相關(guān)源碼,歡迎查閱學(xué)習(xí)。如果有問(wèn)題,或者錯(cuò)誤,歡

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論