在android开发中,算的上常用的View,那ProgressBar是比较常用的View之一了,但是这里有个非常让人头疼的问题,就是系统自带的比较丑陋,但是UI设计出来的效果图和系统的样式差别非常大,这时系统的ProgressBar没法满足用户的需求,于是就有了今天的博文,该博文就是叫你如何打造千变万化的ProgressBar,各种样式,各种参数随心设置,我相信该View一定能满足你在项目中想实现的绝大部分需求。好,那废话就先说到这里,我们开始进入我们今天这边博文的讲解,按照写博文的惯例,先上效果图,是不是有种心动的感觉了,是不是感觉很不错,是不是感觉系统的很丑陋。
1.实现原理:
利用自定View的绘制技术实现.
2.知识储备
a.自定View的绘制流程
b.基本的数学计算
c.字体的宽高计算
d.Canvas类的使用
4.自定义属性
package com.example.circleprogressview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
public class CircleProgress extends View {
private static final int DEFAULT_FIRST_CIRCLE_COLOR = Color.BLACK;
private static final int DEFAULT_FIRST_CIRCLE_WIDTH = 4;
private static final int DEFAULT_SECOND_CIRLCE_COLOR = Color.WHITE;
private static final int DEFAULT_MAX_PROGRESS = 100;
private static final int DEFAULT_START_PROGRESS = 0;
private static final int DEFAULT_PROGRESS_TEXT_COLOR = DEFAULT_SECOND_CIRLCE_COLOR;
private static final int DEFAULT_PROGRESS_TEXT_SIZE = 16;
private static final boolean DEFAULT_IS_SHOW_PROGRESS_TEXT = true;
private static final Cap DEFAULT_CIRCLE_CAP = Cap.SQUARE;
private static final int BUTT_CAP = 0;
private static final int SQUARE_CAP = 1;
private static final int ROUND_CAP = 2;
private int mFirstCircleColor;
private int mFirstCircleWidth;
private int mSecondCircleColor;
private int maxProgress;
private int mStartProgess;
private int mProgressTextColor;
private int mProgressTextSize;
private Paint mPaint;
private boolean isShowProgressText;
private int mCurrentProgress = DEFAULT_START_PROGRESS;
private Cap mCircleCap = DEFAULT_CIRCLE_CAP;
private RectF mOvalRect = new RectF();
public CircleProgress(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int w = getMeasuredWidth();
int h = getMeasuredHeight();
int min = Math.min(w, h);
setMeasuredDimension(min, min);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
// 1.绘制外层圆
int radius = getWidth() / 2 - mFirstCircleWidth / 2;
mPaint.setColor(mFirstCircleColor);
mPaint.setStrokeWidth(mFirstCircleWidth);
mPaint.setStyle(Style.STROKE);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, mPaint);
// 2.绘制圆弧
// 1. 圆弧的半径
// int arcRadius = radius;
// 2.开始角度
// int startAngle = mStartProgess;
// 3.当前角度
int currentProgress = mCurrentProgress;
// 4.计算圆弧区域
mOvalRect.left = mFirstCircleWidth / 2;
mOvalRect.top = mFirstCircleWidth / 2;
mOvalRect.right = getWidth() - mFirstCircleWidth / 2;
mOvalRect.bottom = getHeight() - mFirstCircleWidth / 2;
mPaint.setColor(mSecondCircleColor);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeCap(mCircleCap);
// 5.绘制圆弧
canvas.drawArc(mOvalRect, 0,
(int) (currentProgress * 1.0 / maxProgress * 360), false,
mPaint);
mStartProgess = mCurrentProgress;
// 3.绘制文本
if (isShowProgressText) {
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setTextSize(mProgressTextSize);
mPaint.setColor(mProgressTextColor);
String progressText = (int) (mCurrentProgress * 1.0 / maxProgress * 100)
+ "%";
int w = (int) mPaint.measureText(progressText);
int left = (getWidth() - w) / 2;
FontMetrics metrics = mPaint.getFontMetrics();
int top = (getHeight() - (int) Math.ceil(metrics.descent
+ metrics.ascent)) / 2;
canvas.drawText(progressText, left, top, mPaint);
}
}
public synchronized void setProgress(int progress) {
if (progress > maxProgress) {
progress = maxProgress;
}
if (progress < 0) {
progress = DEFAULT_START_PROGRESS;
}
mCurrentProgress = progress;
if (Looper.getMainLooper() == Looper.myLooper()) {
invalidate();
} else {
postInvalidate();
}
}
public int getProgress() {
return mCurrentProgress;
}
public int getmFirstCircleColor() {
return mFirstCircleColor;
}
public int getmFirstCircleWidth() {
return mFirstCircleWidth;
}
public int getmSecondCircleColor() {
return mSecondCircleColor;
}
public int getMaxProgress() {
return maxProgress;
}
public int getmStartProgess() {
return mStartProgess;
}
public int getmProgressTextColor() {
return mProgressTextColor;
}
public int getmProgressTextSize() {
return mProgressTextSize;
}
public Paint getmPaint() {
return mPaint;
}
public int getmCurrentProgress() {
return mCurrentProgress;
}
public RectF getmOvalRect() {
return mOvalRect;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
}
public boolean isShowProgressText() {
return isShowProgressText;
}
public void setShowProgressText(boolean isShowProgressText) {
this.isShowProgressText = isShowProgressText;
}
public Cap getmCircleCap() {
return mCircleCap;
}
public void setmCircleCap(Cap mCircleCap) {
this.mCircleCap = mCircleCap;
}
public void setmFirstCircleColor(int mFirstCircleColor) {
this.mFirstCircleColor = mFirstCircleColor;
}
public void setmFirstCircleWidth(int mFirstCircleWidth) {
this.mFirstCircleWidth = mFirstCircleWidth;
}
public void setmSecondCircleColor(int mSecondCircleColor) {
this.mSecondCircleColor = mSecondCircleColor;
}
public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress;
}
public void setmStartProgess(int mStartProgess) {
this.mStartProgess = mStartProgess;
}
public void setmProgressTextColor(int mProgressTextColor) {
this.mProgressTextColor = mProgressTextColor;
}
public void setmProgressTextSize(int mProgressTextSize) {
this.mProgressTextSize = mProgressTextSize;
}
public void setmCurrentProgress(int mCurrentProgress) {
this.mCurrentProgress = mCurrentProgress;
}
public CircleProgress(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
// TODO Auto-generated constructor stub
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.CircleProgress);
for (int i = 0; i < typedArray.getIndexCount(); i++) {
switch (typedArray.getIndex(i)) {
case R.styleable.CircleProgress_firstCircleColor:
mFirstCircleColor = typedArray.getColor(i,
DEFAULT_FIRST_CIRCLE_COLOR);
break;
case R.styleable.CircleProgress_firstCircleWidth:
mFirstCircleWidth = (int) typedArray.getDimension(i,
dipTopx(DEFAULT_FIRST_CIRCLE_WIDTH));
break;
case R.styleable.CircleProgress_secondCircleColor:
mSecondCircleColor = typedArray.getColor(i,
DEFAULT_SECOND_CIRLCE_COLOR);
break;
case R.styleable.CircleProgress_maxProgress:
maxProgress = typedArray.getInteger(i, DEFAULT_MAX_PROGRESS);
break;
case R.styleable.CircleProgress_startProgress:
mStartProgess = typedArray
.getInteger(i, DEFAULT_START_PROGRESS);
break;
case R.styleable.CircleProgress_progressTextColor:
mProgressTextColor = typedArray.getColor(i,
DEFAULT_PROGRESS_TEXT_COLOR);
break;
case R.styleable.CircleProgress_progressTextSize:
int textSize = (int) typedArray.getDimension(i,
DEFAULT_PROGRESS_TEXT_SIZE);
mProgressTextSize = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_PX, textSize, getResources()
.getDisplayMetrics());
break;
case R.styleable.CircleProgress_isShowProgressText:
isShowProgressText = typedArray.getBoolean(i,
DEFAULT_IS_SHOW_PROGRESS_TEXT);
break;
case R.styleable.CircleProgress_circleCap:
int index = typedArray.getInt(i, 0);
switch (index) {
case BUTT_CAP:
mCircleCap = Cap.BUTT;
break;
case SQUARE_CAP:
mCircleCap = Cap.SQUARE;
break;
case ROUND_CAP:
mCircleCap = Cap.ROUND;
break;
default:
break;
}
break;
default:
break;
}
}
typedArray.recycle();
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
public CircleProgress(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public int dipTopx(int dip) {
int density = (int) getResources().getDisplayMetrics().density;
return (int) (dip * density + 0.5);
}
}上面的注释写的比较详细了,就不一句句分析代码了.核心方法是onDraw方法。希望各位fork,同时希望各位提出好的建议。
本文介绍了一种自定义安卓圆形进度条的方法,通过继承View并利用Canvas进行绘制,实现了多种样式和参数的自由配置,包括颜色、宽度、文本显示等。
8630

被折叠的 条评论
为什么被折叠?



