生活随笔
收集整理的這篇文章主要介紹了
炫酷的进度条的效果
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
炫酷的進(jìn)度條的效果
自定義view系列之炫酷的進(jìn)度條的效果,讓你的進(jìn)度條從此與眾不同。
按照慣例先上效果圖,俗話說無圖無有真相嘛。
1、帶動畫的進(jìn)度條效果
因?yàn)槲覀兪亲远xview,看到的所有元素都是在onDraw里邊繪制出來的,分析進(jìn)度條效果我們可以分解出幾個(gè)步驟,先繪制底層百分百進(jìn)度條(也就是背景色),再繪制真實(shí)的進(jìn)度。
@Override
protected void onDraw(Canvas canvas
) {super.onDraw(canvas
);canvas
.drawLine(getPaddingLeft(),tipHeight
+ progressMarginTop
,getWidth(),tipHeight
+ progressMarginTop
,bgPaint
);canvas
.drawLine(getPaddingLeft(),tipHeight
+ progressMarginTop
,currentProgress
,tipHeight
+ progressMarginTop
,progressPaint
);}
進(jìn)度條畫完之后就是讓它動起來,我們使用屬性動畫試試改變當(dāng)前進(jìn)度的值重新繪制就可以了,動畫效果我們繼續(xù)使用ValueAnimator
private void initAnimation() {progressAnimator
= ValueAnimator
.ofFloat(0, mProgress
);progressAnimator
.setDuration(duration
);progressAnimator
.setStartDelay(startDelay
);progressAnimator
.setInterpolator(new LinearInterpolator());progressAnimator
.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator
) {float value
= (float) valueAnimator
.getAnimatedValue();textString
= formatNum(format2Int(value
));currentProgress
= value
* mWidth
/ 100;if (progressListener
!= null
) {progressListener
.currentProgressListener(value
);} invalidate();}});progressAnimator
.start();}
到此帶動畫的進(jìn)度條就實(shí)現(xiàn)了,一起看一下效果吧
看到這個(gè)百分比的提示框,你會想到如何實(shí)現(xiàn)吶,很多人會選擇使用圖片然后變更圖片的位置來達(dá)到效果,作為一個(gè)有追求的程序猿怎能滿足于此吶,自己繪制出來豈不更好。很強(qiáng)勢.jpg 接下來我們來分析一下如何繪制這個(gè)帶三角的矩形
這里說一下我們實(shí)現(xiàn)思路:其實(shí)第一次我是準(zhǔn)備從起點(diǎn)到終點(diǎn)用過畫閉合的線做的,需要計(jì)算七個(gè)點(diǎn)的坐標(biāo),最終能實(shí)現(xiàn),但是這種方法太笨了,
在苦思的時(shí)候突然又看了一眼設(shè)計(jì)圖發(fā)現(xiàn)這個(gè)矩形是帶圓角的,我這樣繪制閉合的線是達(dá)不到圓角效果的,等等,圓角?圓角不是可以通過繪制圓角矩形畫出來么,我擦,貌似這是一個(gè)不錯的思路,趕緊去驗(yàn)證。
果不其然,堪稱完美,先繪制一個(gè)圓角矩形,在其下邊繪制一個(gè)三角形,至于里邊的進(jìn)度數(shù)值直接drawText就行了
private void drawTipView(Canvas canvas
) {drawRoundRect(canvas
);drawTriangle(canvas
);}private void drawRoundRect(Canvas canvas
) {rectF
.set(moveDis
, 0, tipWidth
+ moveDis
, tipHeight
);canvas
.drawRoundRect(rectF
, roundRectRadius
, roundRectRadius
, tipPaint
);}private void drawTriangle(Canvas canvas
) {path
.moveTo(tipWidth
/ 2 - triangleHeight
+ moveDis
, tipHeight
);path
.lineTo(tipWidth
/ 2 + moveDis
, tipHeight
+ triangleHeight
);path
.lineTo(tipWidth
/ 2 + triangleHeight
+ moveDis
, tipHeight
);canvas
.drawPath(path
, tipPaint
);path
.reset();}
3、計(jì)算百分比Tip框的起始位置及移動分析
樣式繪制出來接下來就是各種計(jì)算了,先來張手繪圖湊合著看哈
擔(dān)心圖片不清晰就再對圖片內(nèi)容描述一下,重要信息有四個(gè),進(jìn)度的起始點(diǎn)A和B、tip框的起始點(diǎn)M和N,動畫執(zhí)行過程是這樣的:剛開始的時(shí)候只有進(jìn)度條移動,此時(shí)tip框是不動的,當(dāng)進(jìn)度條到達(dá)tip框中間三角形頂點(diǎn)x坐標(biāo)的時(shí)候,tip框跟著進(jìn)度開始一起移動,當(dāng)tip框右邊界到達(dá)整個(gè)進(jìn)度的右邊界的時(shí)候,tip框停止移動,進(jìn)度條繼續(xù)移動一直到終點(diǎn)。
private void initAnimation() {progressAnimator
= ValueAnimator
.ofFloat(0, mProgress
);progressAnimator
.setDuration(duration
);progressAnimator
.setStartDelay(startDelay
);progressAnimator
.setInterpolator(new LinearInterpolator());progressAnimator
.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator
) {float value
= (float) valueAnimator
.getAnimatedValue();textString
= formatNum(format2Int(value
));currentProgress
= value
* mWidth
/ 100;if (progressListener
!= null
) {progressListener
.currentProgressListener(value
);}if (currentProgress
>= (tipWidth
/ 2) &¤tProgress
<= (mWidth
- tipWidth
/ 2)) {moveDis
= currentProgress
- tipWidth
/ 2;}invalidate();}});progressAnimator
.start();}
最終實(shí)現(xiàn)的效果
package com
.allen
.androidcustomview
.widget
;import android
.animation
.ValueAnimator
;
import android
.content
.Context
;
import android
.graphics
.Canvas
;
import android
.graphics
.Color
;
import android
.graphics
.Paint
;
import android
.graphics
.Path
;
import android
.graphics
.Rect
;
import android
.graphics
.RectF
;
import android
.os
.Build
;
import android
.support
.annotation
.Nullable
;
import android
.support
.annotation
.RequiresApi
;
import android
.util
.AttributeSet
;
import android
.util
.TypedValue
;
import android
.view
.View
;
import android
.view
.animation
.LinearInterpolator
;import java
.text
.DecimalFormat
;public class HorizontalProgressBar extends View {private Paint bgPaint
;private Paint progressPaint
;private Paint tipPaint
;private Paint textPaint
;private int mWidth
;private int mHeight
;private int mViewHeight
;private float mProgress
;private float currentProgress
;private ValueAnimator progressAnimator
;private int duration
= 1000;private int startDelay
= 500;private int progressPaintWidth
;private int tipPaintWidth
;private int tipHeight
;private int tipWidth
;private Path path
= new Path();private int triangleHeight
;private int progressMarginTop
;private float moveDis
;private Rect textRect
= new Rect();private String textString
= "0";private int textPaintSize
;private int bgColor
= 0xFFe1e5e8;private int progressColor
= 0xFFf66b12;private RectF rectF
= new RectF();private int roundRectRadius
;private ProgressListener progressListener
;public HorizontalProgressBar(Context context
) {super(context
);}public HorizontalProgressBar(Context context
, @Nullable AttributeSet attrs
) {super(context
, attrs
);init();initPaint();}private void init() {progressPaintWidth
= dp2px(4);tipHeight
= dp2px(15);tipWidth
= dp2px(30);tipPaintWidth
= dp2px(1);triangleHeight
= dp2px(3);roundRectRadius
= dp2px(2);textPaintSize
= sp2px(10);progressMarginTop
= dp2px(8);mViewHeight
= tipHeight
+ tipPaintWidth
+ triangleHeight
+ progressPaintWidth
+ progressMarginTop
;}private void initPaint() {bgPaint
= getPaint(progressPaintWidth
, bgColor
, Paint
.Style
.STROKE
);progressPaint
= getPaint(progressPaintWidth
, progressColor
, Paint
.Style
.STROKE
);tipPaint
= getPaint(tipPaintWidth
, progressColor
, Paint
.Style
.FILL
);initTextPaint();}private void initTextPaint() {textPaint
= new Paint(Paint
.ANTI_ALIAS_FLAG
);textPaint
.setTextSize(textPaintSize
);textPaint
.setColor(Color
.WHITE
);textPaint
.setTextAlign(Paint
.Align
.CENTER
);textPaint
.setAntiAlias(true);}private Paint
getPaint(int strokeWidth
, int color
, Paint
.Style style
) {Paint paint
= new Paint(Paint
.ANTI_ALIAS_FLAG
);paint
.setStrokeWidth(strokeWidth
);paint
.setColor(color
);paint
.setAntiAlias(true);paint
.setStrokeCap(Paint
.Cap
.ROUND
);paint
.setStyle(style
);return paint
;}@Overrideprotected void onMeasure(int widthMeasureSpec
, int heightMeasureSpec
) {int widthMode
= MeasureSpec
.getMode(widthMeasureSpec
);int width
= MeasureSpec
.getSize(widthMeasureSpec
);int heightMode
= MeasureSpec
.getMode(heightMeasureSpec
);int height
= MeasureSpec
.getSize(heightMeasureSpec
);setMeasuredDimension(measureWidth(widthMode
, width
), measureHeight(heightMode
, height
));}private int measureWidth(int mode
, int width
) {switch (mode
) {case MeasureSpec
.UNSPECIFIED
:case MeasureSpec
.AT_MOST
:break;case MeasureSpec
.EXACTLY
:mWidth
= width
;break;}return mWidth
;}private int measureHeight(int mode
, int height
) {switch (mode
) {case MeasureSpec
.UNSPECIFIED
:case MeasureSpec
.AT_MOST
:mHeight
= mViewHeight
;break;case MeasureSpec
.EXACTLY
:mHeight
= height
;break;}return mHeight
;}@Overrideprotected void onDraw(Canvas canvas
) {super.onDraw(canvas
);canvas
.drawLine(getPaddingLeft(),tipHeight
+ progressMarginTop
,getWidth(),tipHeight
+ progressMarginTop
,bgPaint
);canvas
.drawLine(getPaddingLeft(),tipHeight
+ progressMarginTop
,currentProgress
,tipHeight
+ progressMarginTop
,progressPaint
);drawTipView(canvas
);drawText(canvas
, textString
);}private void drawTipView(Canvas canvas
) {drawRoundRect(canvas
);drawTriangle(canvas
);}private void drawRoundRect(Canvas canvas
) {rectF
.set(moveDis
, 0, tipWidth
+ moveDis
, tipHeight
);canvas
.drawRoundRect(rectF
, roundRectRadius
, roundRectRadius
, tipPaint
);}private void drawTriangle(Canvas canvas
) {path
.moveTo(tipWidth
/ 2 - triangleHeight
+ moveDis
, tipHeight
);path
.lineTo(tipWidth
/ 2 + moveDis
, tipHeight
+ triangleHeight
);path
.lineTo(tipWidth
/ 2 + triangleHeight
+ moveDis
, tipHeight
);canvas
.drawPath(path
, tipPaint
);path
.reset();}private void drawText(Canvas canvas
, String textString
) {textRect
.left
= (int) moveDis
;textRect
.top
= 0;textRect
.right
= (int) (tipWidth
+ moveDis
);textRect
.bottom
= tipHeight
;Paint
.FontMetricsInt fontMetrics
= textPaint
.getFontMetricsInt();int baseline
= (textRect
.bottom
+ textRect
.top
- fontMetrics
.bottom
- fontMetrics
.top
) / 2;canvas
.drawText(textString
+ "%", textRect
.centerX(), baseline
, textPaint
);}private void initAnimation() {progressAnimator
= ValueAnimator
.ofFloat(0, mProgress
);progressAnimator
.setDuration(duration
);progressAnimator
.setStartDelay(startDelay
);progressAnimator
.setInterpolator(new LinearInterpolator());progressAnimator
.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator
) {float value
= (float) valueAnimator
.getAnimatedValue();textString
= formatNum(format2Int(value
));currentProgress
= value
* mWidth
/ 100;if (progressListener
!= null
) {progressListener
.currentProgressListener(value
);}if (currentProgress
>= (tipWidth
/ 2) &¤tProgress
<= (mWidth
- tipWidth
/ 2)) {moveDis
= currentProgress
- tipWidth
/ 2;}invalidate();setCurrentProgress(value
);}});progressAnimator
.start();}public HorizontalProgressBar
setProgressWithAnimation(float progress
) {mProgress
= progress
;initAnimation();return this;}public HorizontalProgressBar
setCurrentProgress(float progress
) {mProgress
= progress
;currentProgress
= progress
* mWidth
/ 100;textString
= formatNum(format2Int(progress
));if (currentProgress
>= (tipWidth
/ 2) &¤tProgress
<= (mWidth
- tipWidth
/ 2)) {moveDis
= currentProgress
- tipWidth
/ 2;}invalidate();return this;}public void startProgressAnimation() {if (progressAnimator
!= null
&&!progressAnimator
.isRunning() &&!progressAnimator
.isStarted())progressAnimator
.start();}@RequiresApi(api
= Build
.VERSION_CODES
.KITKAT
)public void pauseProgressAnimation() {if (progressAnimator
!= null
) {progressAnimator
.pause();}}@RequiresApi(api
= Build
.VERSION_CODES
.KITKAT
)public void resumeProgressAnimation() {if (progressAnimator
!= null
)progressAnimator
.resume();}public void stopProgressAnimation() {if (progressAnimator
!= null
) {progressAnimator
.end();}}public interface ProgressListener {void currentProgressListener(float currentProgress
);}public HorizontalProgressBar
setProgressListener(ProgressListener listener
) {progressListener
= listener
;return this;}public static String
formatNumTwo(double money
) {DecimalFormat format
= new DecimalFormat("0.00");return format
.format(money
);}public static String
formatNum(int money
) {DecimalFormat format
= new DecimalFormat("0");return format
.format(money
);}protected int dp2px(int dpVal
) {return (int) TypedValue
.applyDimension(TypedValue
.COMPLEX_UNIT_DIP
,dpVal
, getResources().getDisplayMetrics());}protected int sp2px(int spVal
) {return (int) TypedValue
.applyDimension(TypedValue
.COMPLEX_UNIT_SP
,spVal
, getResources().getDisplayMetrics());}public static int format2Int(double i
) {return (int) i
;}
}
總結(jié)
以上是生活随笔為你收集整理的炫酷的进度条的效果的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。