作者簡(jiǎn)介 原創(chuàng)微信公眾號(hào)郭霖 WeChat ID: guolin_blog
本篇來自猴菇先生的投稿,分享了一個(gè)貝賽爾曲線的應(yīng)用,希望能對(duì)大家有所幫助。
猴菇先生的博客地址:
http://blog.csdn.net/qq_31715429
正文
了解了Android端的貝塞爾曲線,本篇就舉個(gè)栗子練習(xí)一下,仿QQ未讀消息氣泡,是最經(jīng)典的練習(xí)貝塞爾曲線的東東,效果如下:
大體思路就是:
畫兩個(gè)圓,一個(gè)黏連小球固定在一個(gè)點(diǎn)上,一個(gè)氣泡小球跟隨手指的滑動(dòng)改變坐標(biāo)。隨著兩個(gè)圓間距越來越大,黏連小球半徑越來越小。
當(dāng)間距小于一定值,松開手指氣泡小球會(huì)恢復(fù)原來位置;
當(dāng)間距超過一定值之后,黏連小球消失,氣泡小球繼續(xù)跟隨手指移動(dòng),此時(shí)手指松開,氣泡小球消失~
1.首先老一套~新建attrs.xml文件,編寫自定義屬性,新建 DragBubbleView 繼承View,重寫構(gòu)造方法,獲取自定義屬性值,初始化Paint、Path等東東,重寫 onMeasure 計(jì)算寬高,這里不再啰嗦~
2.在 onSizeChanged 方法中確定黏連小球和氣泡小球的圓心坐標(biāo),這里我們?nèi)捀叩囊话耄?/p>
3.經(jīng)分析氣泡小球有以下幾個(gè)狀態(tài):默認(rèn)、拖拽、移動(dòng)、消失,我們這里定義一下,方便根據(jù)不同的狀態(tài)分析不同情況:
4.重寫 onTouchEvent 方法,其中d代表兩圓圓心間距,maxD代表可拖拽的最大間距:
如果控件外面有嵌套 ListView、RecyclerView 等攔截焦點(diǎn)的控件,那就在 ACTION_DOWN 中請(qǐng)求父控件不攔截事件:
getParent().requestDisallowInterceptTouchEvent(true);
然后?ACTION_UP 再把事件還回去:
getParent().requestDisallowInterceptTouchEvent(false);
5.在 onDraw 方法中畫圓、畫貝賽爾曲線、畫消息個(gè)數(shù)文本:
其中計(jì)算 二階貝塞爾曲線 做需要的起點(diǎn)、終點(diǎn) 和 控制點(diǎn)坐標(biāo),順序是 moveTo A, quadTo B, lineTo C, quadTo D, close。先來張示意圖:
手機(jī)可點(diǎn)擊放大查看
再上代碼:
6.氣泡復(fù)原的動(dòng)畫,使用估值器計(jì)算坐標(biāo)
7.順便來個(gè)氣泡狀態(tài)的監(jiān)聽器,方便外部調(diào)用監(jiān)聽其狀態(tài):
8.關(guān)于氣泡爆炸的動(dòng)畫,思路就是放幾張圖片到 drawable 里,然后動(dòng)態(tài)計(jì)數(shù)重繪,在 onDraw 中調(diào)用 canvas.drawBitmap() 方法,具體如下:
在構(gòu)造方法中:
然后在手指抬起的時(shí)候使用如下動(dòng)畫:
最后在 onDraw 中:
9.在布局文件中使用該控件,并使用自定義屬性:
其中android:clipChildren=”false”這個(gè)屬性可以使根布局下的子控件超出本身控件范圍的大小,加上這個(gè)屬性就可以滿屏幕隨意拖拽而不必拘泥于它本身的大小了,炒雞方便~
還有如果覺得在屬性中設(shè)置消息個(gè)數(shù)不方便,需要在代碼中動(dòng)態(tài)獲取數(shù)據(jù)并設(shè)置的話,只要在 DragBubbleView 中添加一個(gè)方法即可
publicvoidsetText(Stringtext){ ? ?mText=text; ? ?invalidate();}
10.在MainActivity中:
總結(jié)
這次既練習(xí)了自定義View,還囊括了貝賽爾曲線,坐標(biāo)的計(jì)算一定要畫圖,簡(jiǎn)單直觀。
項(xiàng)目地址:
https://github.com/MonkeyMushroom/DragBubbleView
完。。。。。。。。。。。。。。。。。。。。。
文章原創(chuàng)作者GuoLin 書籍推薦
郭林大神原創(chuàng)android 書籍:《第一行代碼 android》
