Android自定義View - 仿淘寶淘搶購進(jìn)度條

前言

?????? 最近項目中新增了一個搶購模塊,需要一個進(jìn)度指示條,UI設(shè)計了幾款出來后,PM一看,不行,太low了,沒有逼格 balabala... 后來看到了淘寶的淘搶購模塊,眼前一亮,好 就它了。

????? 吶,就長這樣:

我沒開淘寶店。。。

?????? 當(dāng)時看到這張圖的時候,其實我。。。我是拒絕的。甚至還有點(diǎn)想打人。。。

?????? 不過為了世界和平,還是要給PM點(diǎn)贊。

?????? 吐槽歸吐槽,需求還是要做的(廣大程序員的勞苦心聲。。。)

? ? ? 一番努力過后,終于擼出來了(沒毛病),先給大家看一下實現(xiàn)的最終效果:

高仿山寨版

好了,接下來就一步一步實現(xiàn)該效果。

效果實現(xiàn)

?一. 背景實現(xiàn)

? ? ? 分析:背景邊框是一個圓角矩形,用 canvas.drawRoundRect? 就可以實現(xiàn),背景這里我采用的是一張圖片,轉(zhuǎn)化為Bitmap類型,然后用? canvas.drawBitmap? 繪制出來。

1.繼承View,重寫構(gòu)造方法以及初始化Paint:

因為我這里并沒有 style 等引入, 所以只實現(xiàn)了這兩種構(gòu)造方法,分別用于直接 new 或者是寫到? xml? 里。

2.重寫onSizeChanged? onDraw方法:

sideWidth就是邊框的寬度,其他都是常規(guī),就不一 一解釋了

??? 這里的背景框比較好實現(xiàn):?


???? 需要注意的一點(diǎn)是, drawRoundRect? 還要其他類似的重載方法:

這個只支持5.0以上,所以這里就沒有采用

?????? 條紋背景就稍微麻煩一點(diǎn)了。本來我想著是不是可以通過循環(huán)? drawRectF?? 出每一個小條紋,后來想著太麻煩了,就讓UI幫我做了一張圓角條紋圖,然后直接? drawBitmap? 進(jìn)去。

參數(shù)解釋一下:1. bitmap對象??? 2. srcRect :即繪制原圖的區(qū)域,說白了,就是截圖原圖的哪一部分進(jìn)行繪制,為 null 的話,就是截取全部?? 3. dstRectF :繪制的目標(biāo)區(qū)域,就是把截取后的圖片繪制到哪一塊。 4.? Paint? 畫筆? 可以為null

????????? 但是這樣做有個弊端,就是如果UI做的圖不是剛好圓角的話,那么左右兩邊的圖片會溢出圓角矩形一點(diǎn),效果不好,類似這樣:

左右兩邊不是剛好圓角的情況

? ? ? ? 無奈之下,只好使用大殺器? PorterDuffXfermode, 圖形混合模式,這里還是借用一張經(jīng)典的圖吧,相信大家都看過了:

?????? 一般的寫法就是這樣:

? ????? 什么意思呢,給大家解釋一下:先建立兩個概念

這段代碼沒有什么實質(zhì)意義,不用糾結(jié),只要記住?? bitmap1? 是 dst? , bitmap2? 是 src ,即當(dāng) paint 設(shè)置了該模式后繪制的圖形,為 src

? ? ? ? 當(dāng)給 Paint 設(shè)置了不同模式的? PorterDuffXfermode ,dst? 與? src 發(fā)生部分重疊或者其他情況時(一般都是用于部分重疊),那么 dst? ? src? 就會按照對應(yīng)的混合模式進(jìn)行顯示。就比如 SRC_IN? 模式,對照上文提到的經(jīng)典圖,圓形和矩形發(fā)生重疊的部分是一個扇形,圓形是? dst ,矩形是? src, 那么按照? SRC_IN 模式,重疊的? src? 部分進(jìn)行保留,其他的部分就不顯示了,這樣就完成了圖形混合。?

??????? 在這里只能簡單的解釋一下了,太深入的話感覺這個進(jìn)度條完不成了啊 (太深入我也不會了 〒▽〒) ,只要這里理解了,那么本文的自定義view也就完成一半了。

??????? 好了,接下來就是正式的開始繪制背景圖了。


????? a). 先創(chuàng)建一個空的 bitmap 裝載在一個新的畫布上,然后在畫布上繪制一個 圓角矩形,以不遮擋之前繪制好的背景邊框為準(zhǔn)。

????? b). 然后為 paint 設(shè)置 SRC_IN 的圖形混合模式,再在該畫布上把我們做好的條紋圖繪制進(jìn)來,這樣,之前繪制的圓角矩形就做為? dst ,后來繪制的條紋圖就做為 src

????? c). 這樣,重疊的部分始終是圓角矩形范圍,而且 條紋圖 會把這個 圓角矩形填充滿(因為在繪制條紋圖時設(shè)置的 dstRectF 和圓角矩形一致)。

????? d). 根據(jù)? SRC_IN 的規(guī)則,條紋圖與圓角矩形重疊的部分保留,溢出的部分則不予顯示,這樣的話,就算 UI 給的圖不是剛好圓角,也是可以滿足需求的。

還有一點(diǎn)需要注意的事,給 Paint? 設(shè)置混合模式,繪制完后,如果還要繪制其他東西,則取消混合模式,即? setXfermode( null )

????? 背景終于繪制出來了:

還可以哈

二. 進(jìn)度條實現(xiàn)

?????? 分析:其實繪制進(jìn)度條和繪制背景圖原理一樣,只是換了一張和背景紋理一樣但是顏色不同的圖片,還有一點(diǎn)就是,進(jìn)度條的寬度需要根據(jù)比例來進(jìn)行調(diào)整,那么就在為 進(jìn)度條繪制 dst 圓角矩形的時候,根據(jù)比例設(shè)置該圓角矩形的寬度就行了啊。

???????????? 這里我就直接上代碼了:

scale就是售出商品的比例,這個會根據(jù)傳入的 商品總量以及 售出量進(jìn)行計算

?????????? 可以看到,和繪制 背景 的時候原理相同,唯一不同的是,做為 dst 的圓角矩形在繪制時,寬度會根據(jù)比例進(jìn)行調(diào)整。

?????????? 做為? src? 的進(jìn)度圖片在繪制的時候,繪制的區(qū)域還是整個 View 的圓角矩形區(qū)域,這樣可以保證 進(jìn)度條圖片不會變形。

?????????? 還有一點(diǎn)需要注意的是,進(jìn)度條圖片 與 背景圖片 紋理最好保持一致,這樣實現(xiàn)的效果才比較美觀,不然分分鐘逼死強(qiáng)迫癥。

看到曙光了

三. 文字實現(xiàn)

還有最后一個部分,就是文字信息繪制。

??????? 分析:文字繪制這一塊,其實難度不大,就是用?? drawText? 進(jìn)行繪制,控制好繪制的起點(diǎn)坐標(biāo),然后根據(jù)售出比例調(diào)整即可。唯一的難點(diǎn)就在于文字的變色,當(dāng)進(jìn)度條覆蓋在文字上時,要顯示出白色的文字。

??????? 其實這個想一下是不是可以用我們之前畫進(jìn)度條的思路來解決:

??????? 1. 先把紅色的文字全部繪制出來。

??????? 2. 然后繪制一個跟隨進(jìn)度變化的白色圓角矩形區(qū)域。

??????? 3. 那么該白色圓角矩形區(qū)域與文字的重疊部分,不就是文字線條部分嗎?(想象一下蓋章的時候,白紙就是我們的白色圓角矩形,章上面的字就是我們的文字,只不過章上面的字是突起的,蓋章的時候不就是章上突起的字與白紙接觸的地方被染上印泥了嗎。)

??????? 4.上面一條理解了,再來分析我們的實現(xiàn)思路,當(dāng)白色圓角矩形區(qū)域與文字重疊的時候,把重疊區(qū)域染成白色,不就成了白色的文字了嗎。

??????? 5.用代碼實現(xiàn)就是 :把 白色圓角矩形當(dāng)做? src ,之前寫好的紅色文字為? dst ,采用? SRC_IN? 的圖形混合模式,顯示出重疊部分的? src 就可以實現(xiàn)該效果了。

好了,上代碼:

現(xiàn)在看這些代碼應(yīng)該很清晰了吧,主要注意點(diǎn)就是根據(jù)? scale? 繪制不同的文字

?????????? 這里再提一點(diǎn)就是,繪制 text 的時候,起始點(diǎn)的坐標(biāo)就是文字左下角 的 基準(zhǔn)點(diǎn),而不是左上角,至于基準(zhǔn)點(diǎn)的 Y

坐標(biāo),一般的計算方法就是:

網(wǎng)上對于這個有很詳細(xì)的解釋,這里就不過多介紹了,流傳的版本也挺多。。。這一種是我都試過后感覺比較合適的

?????????? 如果需要動畫效果的話(就是設(shè)置了固定進(jìn)度后,進(jìn)度條會一點(diǎn)一點(diǎn)走過去,而不是瞬間完成),這里只需要另外設(shè)置一個新的變量代替 當(dāng)前進(jìn)度,而且讓該新變量從0自增至當(dāng)前進(jìn)度大小,自增過程中讓 View 重繪就可以了。


總結(jié)

? ? ? 好了,這一個自定義? View? 已經(jīng)被我們完成了(其實還有很多其他的方案,我一開始是想繼承? ProgressBar,但是思路上大都差不多,有興趣的可以自己動手實現(xiàn)一下哈),大家可以發(fā)現(xiàn),乍看一下感覺很難很復(fù)雜的 View,在拆分成一個個小模塊后,問題也就迎刃而解了,所以嘛,不要感覺 自定義 View 是一個很難的東西,Google? 已經(jīng)為我們封裝了一套很完善的 api ,剩下的就靠我們的想象力了。

寫在最后

????? 本人剛開始寫博客,文筆生疏,排版不佳,有些地方表述的不太清楚,個人的理解也有不全面的地方,望各位看官輕噴。有任何的意見或者建議歡迎給我留言。

? ? ? 項目我已經(jīng)上傳到 github 了,有興趣的可以去看一下,順手一個 Star? 也是極好的 ●_●

????? Github 地址:https://github.com/zhlucky/SaleProgressView?





最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容