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

前言

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

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

我沒開淘寶店。。。

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

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

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

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

高仿山寨版

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

效果實(shí)現(xiàn)

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

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

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

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

2.重寫onSizeChanged? onDraw方法:

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

????? c). 這樣,重疊的部分始終是圓角矩形范圍,而且 條紋圖 會(huì)把這個(gè) 圓角矩形填充滿(因?yàn)樵诶L制條紋圖時(shí)設(shè)置的 dstRectF 和圓角矩形一致)。

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

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

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

還可以哈

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

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

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

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

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

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

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

看到曙光了

三. 文字實(shí)現(xiàn)

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

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

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

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

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

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

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

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

好了,上代碼:

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

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

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

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

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


總結(jié)

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

寫在最后

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

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

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





最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,720評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,690評論 2 370

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