寫在前面:
本篇可能是手把手自定義view系列最后一篇了,實際上我也是一周前才開始真正接觸自定義view,通過這一周的練習,基本上已經熟練自定義view,能夠應對一般的view需要,那么就以本篇來結尾告一段落,搞完畢設的開題報告后去學習新的內容。
有人對我說類似的效果網上已經有了呀,直接拿來就可以用,為什么還要寫。我個人的觀點是:第三方控件多數不能完全滿足UI的要求,如果需要修改,那么必須理解他的實現,所以很有必要自己去寫一款出來,成為程序的創造者,而不單單是使用者。所以,寫一寫已經實現的效果,對學習來說還是很重要的。我相信,等從使用者變成創造者之后,會有很大的提高。
轉載請注明出處:http://blog.csdn.net/wingichoy/article/details/50482271
好了,前面說的有點多。。那么開始正題,這次實現的是一個帶有動畫效果的loading, ?難度比之前的所有文章都要復雜。但是其實一步一步分解做下來,用心去做還是不難的。
為了美觀一些,我把它放到了dialog里面 ? 上效果圖:?

怎么樣!是不是很炫酷,自我感覺很融入系統,像原生的東西#王婆賣瓜#
開始之前。我想說一下我的大體思路,不知道有沒有更好的方法。歡迎拍磚指點交流!
對于動畫效果,我全局采用一種percent,和標記位思想。也就是繪制分段,如果不達到100%,就一直畫到底。如:對于一條線,從一端畫到另一端,他的第二個點的坐標不斷變化,我就用 最終的長度 * 百分比 來作為過度時期的變量, 即canvas.drawLine(0,0,x * percent /100,y * percent /100); ? ?標記位的話就一一個boolean值,如果來判斷該怎么畫。 缺點也很明顯:每次都要if 他percent到沒到100% ?嵌套太多次,不知道有沒有解決辦法。
現在來分析一下動畫的過程。基礎的坐標計算一下就好,這里就不多說,如果你這些還不熟練,你可以看看我之前的文章:[手把手帶你繪制一個時尚儀表盤](http://blog.csdn.net/wingichoy/article/details/50468674)
1.首先要做的是繪制出來剛開始靜態的圓和箭頭, 箭頭用path畫。
2.是豎線縮短的過程,變成一個點。
3.箭頭變橫線。
4.點被橫線拋出到圓。
5.按百分比繪制的弧,同時直線變對勾。
之后我們就一個一個來畫。構造函數測量的就省去了。
那么 拿起你的paint 開始跟我一起draw吧
初始化一下畫筆
~~~
Paint p = new Paint();
Path path = new Path();
p.setColor(Color.parseColor("#2EA4F2"));
p.setStyle(Paint.Style.STROKE);
p.setStrokeWidth(8);
p.setAntiAlias(true);
//百分比弧的矩形
RectF rectF = new RectF(5, 5, mWidth - 5, mHeight - 5);
//繪制圓
canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2 - 5, p);
~~~
這里設置一個標志位,用于標記是否可以開始繪制動畫。
~~~
if (canStartDraw) {
isDrawing = true;
~~~
如果不可以,則繪制靜態的箭頭。
~~~
else {
//繪制靜態箭頭
p.setColor(Color.WHITE);
canvas.drawLine(mWidth / 2, mHeight / 4, mWidth / 2, mHeight * 0.75f, p);
// Path path = new Path();
path.moveTo(mWidth / 4, mHeight * 0.5f);
path.lineTo(mWidth / 2, mHeight * 0.75f);
path.lineTo(mWidth * 0.75f, mHeight * 0.5f);
canvas.drawPath(path, p);
}
~~~
現在的效果是這樣的

2.線變成一個點。 這里的效果其實就是不斷繪制一個線,基本上坐標的變化可以用如下表示: ? x,y1+percent,x,y2-percent.
那么這里就開始drawLine ? 用百分比控制具體的變化量。 ? 這里為什么percent 不自增到100呢,原因是線最終要縮短成和點一樣的大小,并非消失。這里就完成了第一階段的動畫。
~~~
isDrawing = true;
//開始變形
p.setColor(Color.WHITE);
//如果小于95 就繼續縮短。 95是微調值 和point大小相等
if (mLineShrinkPercent < 95) {
//線段逐漸縮短(終點為mWidth/2,mHeight/2)
float tmp = (mWidth / 2 - mHeight / 4) * mLineShrinkPercent / 100;
canvas.drawLine(mWidth / 2, mHeight / 4 + tmp, mWidth / 2, mHeight * 0.75f - tmp, p);
mLineShrinkPercent += 5;
} else {
~~~

3.箭頭變橫線 ? 由于箭頭是Path畫的,所以我們只要改變path中間那個點的y坐標就可以了。 這里需要注意的是 在變成西線的過程中,點是一直存在的,所以要畫一個circle上去(為什么不point,因為他很方= =),也是用一個百分比來控制。
~~~
//path變成直線
isPathToLine = true;
if (mPathPercent < 100) {
path.moveTo(mWidth / 4, mHeight * 0.5f);
path.lineTo(mWidth / 2, mHeight * 0.75f - mPathPercent / 100f * 0.25f * mHeight);
path.lineTo(mWidth * 0.75f, mHeight * 0.5f);
canvas.drawPath(path, p);
mPathPercent += 5;
//在變成直線的過程中這個點一直存在
canvas.drawCircle(mWidth / 2, mHeight / 2,2.5f, p);
} else {
~~~
4.點被橫線拋出到圓弧上,同樣也是百分比控制。 ? 最終的圓心坐標為 mWidth/2,0
~~~
//繪制把點上彈的直線
//畫上升的點
if (mRisePercent < 100) {
//在點移動到圓弧上的時候 線是一直存在的
canvas.drawLine(mWidth / 4, mHeight * 0.5f, mWidth * 0.75f, mHeight * 0.5f, p);
canvas.drawCircle(mWidth / 2, mHeight / 2 - mHeight / 2 * mRisePercent / 100 + 5,2.5f, p);
mRisePercent += 5;
} else
~~~
5.按百分比繪制的弧,同時直線變對勾。 弧的話,注意一下起始弧度是270, 繪制弧度為360*percent就可以。對勾跟上面一樣,因為本身是一條Path,這次同時改變第二個點和第三個點就可以了。
~~~
//上升的點最終的位置
canvas.drawPoint(mWidth / 2, 5, p);
isRiseDone = true;
//改變對勾形狀
if (mLinePercent < 100) {
path.moveTo(mWidth / 4, mHeight * 0.5f);
path.lineTo(mWidth / 2, mHeight * 0.5f+ mLinePercent/100f * mHeight * 0.25f);
path.lineTo(mWidth * 0.75f, mHeight * 0.5f - mLinePercent / 100f * mHeight * 0.3f);
canvas.drawPath(path, p);
mLinePercent += 5;
//動態繪制圓形百分比
if (mCirclePercent < 100) {
canvas.drawArc(rectF, 270, -mCirclePercent / 100.0f * 360, false, p);
mCirclePercent += 5;
}
~~~
6.(為什么有6??) 很重要的一點,切忌不要忘記。如果你只寫了以上代碼,你運行完會發現所有繪圖都消失了! 那是因為percent超過100就不進行繪制了,所以在最外面的else里需要繪制一個圓加一個對號。完成之后直接? postInvalidateDelayed(10);
~~~
<pre name="code" class="java">else {
//繪制最終的path
path.moveTo(mWidth / 4, mHeight * 0.5f);
path.lineTo(mWidth / 2, mHeight * 0.75f);
path.lineTo(mWidth * 0.75f, mHeight * 0.3f);
canvas.drawPath(path, p);
// 繪制最終的圓
canvas.drawArc(rectF, 270, -360, false, p);
isDrawing = false;
}
~~~
7.(還有7,你逗我?)加一個start方法 用于重置各種標記位
~~~
public void start() {
if (isDrawing == false) {
canStartDraw = true;
isRiseDone = false;
mRisePercent = 0;
mLineShrinkPercent = 0;
mCirclePercent = 0;
mPathPercent = 0;
mLinePercent = 0;
invalidate();
}
}
~~~
之后就大功告成了!!!
本項目地址:?[點擊打開鏈接](https://github.com/githubwing/LoadingView)? ?求關注 ?求評論 ?求star ? ?那么,手把手帶你寫view系列就基本完結了。
手把手番外篇:[ 手把手教你畫一個 逼格滿滿圓形水波紋loadingview Android](http://blog.csdn.net/wingichoy/article/details/50523713)
- 前言
- android自定義viewgroup初步之一----抽屜菜單
- Android 自定義view --圓形百分比(進度條)
- Android 自定義View -- 簡約的折線圖
- 新手自定義view練習實例之(一) 泡泡彈窗
- 新手自定義view練習實例之(二) 波浪view
- 手把手帶你畫一個 時尚儀表盤 Android 自定義View
- 手把手帶你畫一個動態錯誤提示 Android自定義view
- 手把手帶你做一個超炫酷loading成功動畫view Android自定義view
- 關于Android自定義view 你所需要知道的基本函數
- Android自定義view進階-- 神奇的貝塞爾曲線
- wing帶你玩轉自定義view系列(1) 仿360內存清理效果
- wing帶你玩轉自定義view系列(2) 簡單模仿qq未讀消息去除效果
- wing帶你玩轉自定義view系列(3)模仿微信下拉眼睛
- 手把手教你畫一個 逼格滿滿圓形水波紋loadingview Android
- 有坑?? 為何wing墜入PorterDuffXferMode的萬丈深淵(PorterDuffXferMode深入試驗)
- 手把手帶你畫一個漂亮蜂窩view Android自定義view
- 一個炫字都不夠??!!!手把手帶你打造3D自定義view
- 恭喜發財! -- 手把手教你仿造一個qq下拉搶紅包 Android自定義view