Android自定义圆形进度条
生活随笔
收集整理的這篇文章主要介紹了
Android自定义圆形进度条
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Android自定義圓形進度條
github地址:https://github.com/opq1289/CircleProgressView
效果圖:
無動畫:
有動畫:
整圓:
切割圓:具體步驟:
1. 繪制最基礎的兩個圓
定義兩個畫筆:
//進度條畫筆 mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mProgressPaint.setStyle(Paint.Style.STROKE); mProgressPaint.setStrokeWidth(30); mProgressPaint.setColor(Color.parseColor("#d81b60")); //背景圓畫筆 mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mBackgroundPaint.setStyle(Paint.Style.STROKE); mBackgroundPaint.setStrokeWidth(30); mBackgroundPaint.setColor(Color.parseColor("#f1f1f1")); 復制代碼畫圓:
mRectf = new RectF(0, 0, 200, 200); canvas.drawCircle(100, 100, 100, mBackgroundPaint); canvas.drawArc(mRectf, 0, 120, false, mProgressPaint); 復制代碼邊緣被切割,增加參數進度條寬度,優化邊緣:
private void initPaint() {//進度條畫筆mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mProgressPaint.setStyle(Paint.Style.STROKE);mProgressPaint.setStrokeWidth(mProgressWidth);mProgressPaint.setColor(Color.parseColor("#d81b60"));//背景圓畫筆mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mBackgroundPaint.setStyle(Paint.Style.STROKE);mBackgroundPaint.setStrokeWidth(mProgressWidth);mBackgroundPaint.setColor(Color.parseColor("#f1f1f1")); }@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);mRectf = new RectF(mProgressWidth / 2, mProgressWidth / 2, 200 - mProgressWidth / 2, 200 - mProgressWidth / 2);canvas.drawCircle(100, 100, 100 - mProgressWidth / 2, mBackgroundPaint);canvas.drawArc(mRectf, 0, 120, false, mProgressPaint); } 復制代碼2. 計算尺寸
main_activity.xml中的布局是:
android:layout_width="100dp" android:layout_height="100dp" 復制代碼顯示布局邊界后發現view的寬高是屏幕寬高:
重新設置view的尺寸:
//設置默認最小尺寸 private int mDefaultWidth = CommonUtil.dp2px(getContext(), 10); 復制代碼@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = measureWidth(widthMeasureSpec);int height = measureHeight(heightMeasureSpec);mViewWidth = Math.min(width, height);setMeasuredDimension(mViewWidth, mViewWidth); } 復制代碼private int measureWidth(int widthMeasureSpec) {int width;int size = MeasureSpec.getSize(widthMeasureSpec);int mode = MeasureSpec.getMode(widthMeasureSpec);switch (mode) {case MeasureSpec.EXACTLY:width = size < mProgressWidth ? mProgressWidth : size;break;case MeasureSpec.AT_MOST:width = mDefaultWidth * 2;break;default:width = CommonUtil.getScreenWidthInPx(getContext());break;}return width; }private int measureHeight(int heightMeasureSpec) {int height;int size = MeasureSpec.getSize(heightMeasureSpec);int mode = MeasureSpec.getMode(heightMeasureSpec);switch (mode) {case MeasureSpec.EXACTLY:height = size < mProgressWidth ? mProgressWidth : size;break;case MeasureSpec.AT_MOST:height = mDefaultWidth * 2;break;default:height = CommonUtil.getScreenHeightInPx(getContext());break;}return height; } 復制代碼然后修改繪制:
@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);mRectf = new RectF(mProgressWidth / 2, mProgressWidth / 2, mViewWidth - mProgressWidth / 2, mViewWidth - mProgressWidth / 2);canvas.drawCircle(mViewWidth / 2, mViewWidth / 2, mViewWidth / 2 - mProgressWidth / 2, mBackgroundPaint);canvas.drawArc(mRectf, 0, 120, false, mProgressPaint); } 復制代碼至此,靜態進度條就畫好了。
將參數設置為動態,通過方法和屬性設置。
<declare-styleable name="CircleProgressView"><attr name="progressWidth" format="dimension"/><attr name="progressColor" format="reference"/><attr name="backgroundColor" format="reference"/><attr name="startAngle" format="integer"/> </declare-styleable>復制代碼public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initPaint();TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.CircleProgressView, defStyleAttr, 0);mProgressWidth = (int) typedArray.getDimension(R.styleable.CircleProgressView_progressWidth, mDefaultWidth);mProgressColor = (int) typedArray.getDimension(R.styleable.CircleProgressView_progressColor, ContextCompat.getColor(getContext(), R.color.colorAccent));mStartAngle = typedArray.getInt(R.styleable.CircleProgressView_startAngle, 0);mEndAngle = typedArray.getInt(R.styleable.CircleProgressView_startAngle, 360);mBackgroundColor = (int) typedArray.getDimension(R.styleable.CircleProgressView_backgroundColor, ContextCompat.getColor(getContext(), R.color.grey_f1));typedArray.recycle();mProgressPaint.setStrokeWidth(mProgressWidth);mProgressPaint.setColor(mProgressColor);mBackgroundPaint.setStrokeWidth(mProgressWidth);mBackgroundPaint.setColor(mBackgroundColor); }復制代碼3. 添加動畫
public void setProgress(float progress) {mValueAnimator = ValueAnimator.ofFloat(progress);mValueAnimator.setDuration(1000);mValueAnimator.setInterpolator(new LinearInterpolator());mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {mProgress = (float) animation.getAnimatedValue();invalidate();}});mValueAnimator.start(); }復制代碼增加進度監聽:
public interface OnProgressChangedListener {void onProgressChanged(float currentProgress); }復制代碼public void setOnProgressChangedListener(OnProgressChangedListener listener) {mListener = listener; }復制代碼在布局中增加文字,設置居中:
4. 優化代碼
增加靜態和動畫的區分:
/** * @param progress 進度 * @param showAnimation 是否展示動畫 */ public void setProgress(float progress, boolean showAnimation) {mShowAnimation = showAnimation;if (mValueAnimator != null && mValueAnimator.isRunning()) {mValueAnimator.cancel();}if (mShowAnimation) {mValueAnimator = ValueAnimator.ofFloat(progress);mValueAnimator.setDuration(mDuration);mValueAnimator.setInterpolator(new LinearInterpolator());mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {mProgress = (float) animation.getAnimatedValue();if (mListener != null) {mListener.onProgressChanged(mProgress);}invalidate();}});mValueAnimator.start();} else {mProgress = progress;invalidate();} }復制代碼設置畫筆類型,增加圓頭畫筆:
public void setCap(Paint.Cap cap) {mProgressPaint.setStrokeCap(cap);mBackgroundPaint.setStrokeCap(cap); }復制代碼5. 增加切割圓類型
增加進度條類型mProgressType:
/*** 整圓進度條*/ public static final int TYPE_CIRCLE = 0; /*** 切割圓進度條*/ public static final int TYPE_CLIP = 1;復制代碼切割圓從開始角度到結束角度之間,總進度為100。所以這種情況下:總進度=終止角度 - 起始角度
設置進度的方法修改:
public void setProgress(float progress, boolean showAnimation) {mShowAnimation = showAnimation;if (mProgressType == TYPE_CLIP) {progress = (int) ((mEndAngle - mStartAngle) * 100 / 360.0f);mTotalProgress = progress;} else {mTotalProgress = 100;}if (mValueAnimator != null && mValueAnimator.isRunning()) {mValueAnimator.cancel();}if (mShowAnimation) {mValueAnimator = ValueAnimator.ofFloat(progress);mValueAnimator.setDuration(mDuration);mValueAnimator.setInterpolator(new LinearInterpolator());mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {mProgress = (float) animation.getAnimatedValue();if (mListener != null) {mListener.onProgressChanged(mProgress * 100 / mTotalProgress);}invalidate();}});mValueAnimator.start();} else {mProgress = progress;invalidate();} }復制代碼OnDraw修改,區分切割圓和整圓:
@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);mRectf = new RectF(mProgressWidth / 2, mProgressWidth / 2, mViewWidth - mProgressWidth / 2, mViewWidth - mProgressWidth / 2);if (mProgressType == TYPE_CIRCLE) {canvas.drawCircle(mViewWidth / 2, mViewWidth / 2, mViewWidth / 2 - mProgressWidth / 2, mBackgroundPaint);canvas.drawArc(mRectf, mStartAngle, mProgress * 360 / 100, false, mProgressPaint);} else if (mProgressType == TYPE_CLIP) {canvas.drawArc(mRectf, mStartAngle, mEndAngle - mStartAngle, false, mBackgroundPaint);canvas.drawArc(mRectf, mStartAngle, mProgress * 360 / 100, false, mProgressPaint);} }復制代碼完成。
github地址:https://github.com/opq1289/CircleProgressView
總結
以上是生活随笔為你收集整理的Android自定义圆形进度条的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 广西发布品牌“出海”三年行动计划 布局海
- 下一篇: 使用C++版本Mxnett进行预测的注意