1.使用TypedValue将dp或者sp转换为px
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,getResources().getDisplayMetrics());
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,getResources().getDisplayMetrics());
2.Paint.ascent():baseline之上至字符最高处的距离;
Paint.descent():baseline之下至字符最低处的距离;
Paint.measureText():获取字符串的宽度;
Paint.getTextBounds():获取字符串的边界宽度;
3.绘制文字的基准线
int y = (int) (-(mPaint.ascent() + mPaint.descent()) / 2);
4.resolveSize
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
final int specMode = MeasureSpec.getMode(measureSpec);
final int specSize = MeasureSpec.getSize(measureSpec);
final int result;
switch (specMode) {
case MeasureSpec.AT_MOST:
if (specSize < size) {
result = specSize | MEASURED_STATE_TOO_SMALL;
} else {
result = size;
}
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
case MeasureSpec.UNSPECIFIED:
default:
result = size;
}
return result | (childMeasuredState & MEASURED_STATE_MASK);
}
5.水平进度条完整代码
public class HorizontalProgressBar extends ProgressBar {
private static final int DEFAULT_TEXT_SIZE = 10;
private static final int DEFAULT_TEXT_COLOR = 0xFFFF0000;
private static final int DEFAULT_TEXT_OFFSET = 10;
private static final int DEFAULT_REACH_COLOR = 0xFFFF0000;
private static final int DEFAULT_REACH_HEIGHT = 2;
private static final int DEFAULT_UNREACH_COLOR = 0x44FF0000;
private static final int DEFAULT_UNREACH_HEIGHT = 2;
protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
protected int mTextColor = DEFAULT_TEXT_COLOR;
protected int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);
protected int mReachColor = DEFAULT_REACH_COLOR;
protected int mReachHeight = dp2px(DEFAULT_REACH_HEIGHT);
protected int mUnreachColor = DEFAULT_UNREACH_COLOR;
protected int mUnreachHeight = dp2px(DEFAULT_UNREACH_HEIGHT);
protected Paint mPaint = new Paint();
protected int mRealWidth;
public HorizontalProgressBar(Context context) {
this(context, null);
}
public HorizontalProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizontalProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.HorizontalProgressBar);
mTextColor = typedArray.getColor(R.styleable.HorizontalProgressBar_progress_text_color, mTextColor);
mTextSize = (int) typedArray.getDimension(R.styleable.HorizontalProgressBar_progress_text_size, mTextSize);
mTextOffset = (int) typedArray.getDimension(R.styleable.HorizontalProgressBar_progress_text_offset, mTextOffset);
mReachColor = typedArray.getColor(R.styleable.HorizontalProgressBar_progress_reach_color, mReachColor);
mReachHeight = (int) typedArray.getDimension(R.styleable.HorizontalProgressBar_progress_reach_height, mReachHeight);
mUnreachColor = typedArray.getColor(R.styleable.HorizontalProgressBar_progress_unreach_color, mUnreachColor);
mUnreachHeight = (int) typedArray.getDimension(R.styleable.HorizontalProgressBar_progress_unreach_height, mUnreachHeight);
typedArray.recycle();
mPaint.setTextSize(mTextSize);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = measureHeightSize(heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
mRealWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
}
private int measureHeightSize(int heightMeasureSpec) {
int result = 0;
int size = MeasureSpec.getSize(heightMeasureSpec);
int mode = MeasureSpec.getMode(heightMeasureSpec);
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
int textHeight = (int) (mPaint.ascent() - mPaint.descent());
result = getPaddingTop() + getPaddingBottom() +
Math.max(Math.max(mReachHeight, mUnreachHeight), Math.abs(textHeight));
if (mode == MeasureSpec.AT_MOST) {
result = Math.min(result, size);
}
}
return result;
}
@Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
//文字长度
String text = getProgress() + "%";
int textWidth = (int) mPaint.measureText(text);
canvas.save();
//画布坐标平移到paddingLeft,1/2高度处
canvas.translate(getPaddingLeft(), getHeight() / 2);
//进度比例
float radio = getProgress() * 1.0f / getMax();
//第一段长度
float progressX = (mRealWidth - textWidth - mTextOffset) * radio;
// float endX = progressX - mTextOffset/2;
//是否需要绘制第二段
boolean noNeedUnreach = false;
if (progressX + textWidth + mTextOffset / 2 > mRealWidth) {
progressX = mRealWidth - textWidth - mTextOffset / 2;
noNeedUnreach = true;
}
//绘制第一段进度条
mPaint.setColor(mReachColor);
mPaint.setStrokeWidth(mReachHeight);
canvas.drawLine(0, 0, progressX, 0, mPaint);
//绘制文字
mPaint.setColor(mTextColor);
int y = (int) (-(mPaint.ascent() + mPaint.descent()) / 2);
canvas.drawText(text, progressX + mTextOffset / 2, y, mPaint);
//绘制第二段
if (!noNeedUnreach) {
mPaint.setColor(mUnreachColor);
mPaint.setStrokeWidth(mUnreachHeight);
canvas.drawLine(progressX + textWidth + mTextOffset, 0, mRealWidth, 0, mPaint);
}
canvas.restore();
}
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());
}
}
4.圆形进度条完整代码
public class RoundProgressBar extends HorizontalProgressBar {
private int mRadius = dp2px(30);
private int mMaxPaintWidth;
public RoundProgressBar(Context context) {
this(context, null);
}
public RoundProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.RoundProgressBar);
mRadius = (int) typedArray.getDimension(R.styleable.RoundProgressBar_progress_radius, mRadius);
typedArray.recycle();
mReachHeight = (int) (mReachHeight * 2.5f);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mMaxPaintWidth = Math.max(mReachHeight, mUnreachHeight);
int expect = mRadius * 2 + mMaxPaintWidth + getPaddingLeft() + getPaddingRight();
int widthSize = resolveSize(expect, widthMeasureSpec);
int heightSize = resolveSize(expect, heightMeasureSpec);
setMeasuredDimension(widthSize, heightSize);
int realWidth = Math.min(widthSize, heightSize);
mRadius = (realWidth - getPaddingLeft() - getPaddingRight() - mMaxPaintWidth) / 2;
}
@Override
protected synchronized void onDraw(Canvas canvas) {
String text = getProgress() + "%";
int textWidth = (int) mPaint.measureText(text);
int textHeight = (int) (mPaint.ascent() - mPaint.descent());
canvas.save();
//绘制圆
canvas.translate(getPaddingLeft() + mMaxPaintWidth / 2, getPaddingTop() + mMaxPaintWidth / 2);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(mUnreachColor);
mPaint.setStrokeWidth(mUnreachHeight);
canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
//绘制弧
mPaint.setColor(mReachColor);
mPaint.setStrokeWidth(mReachHeight);
float sweep = getProgress() * 1.0f / getMax() * 360;
canvas.drawArc(new RectF(0, 0, mRadius *2 , mRadius *2), 0, sweep, false, mPaint);
//绘制文字
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(mTextColor);
mPaint.setStrokeWidth(mTextSize);
canvas.drawText(text, mRadius - textWidth / 2, mRadius - textHeight / 2, mPaint);
canvas.restore();
}
}