完整代码

自定义属性xml文件


<?xml version="1.0" encoding="utf-8"?>
<resources>


<declare-styleable name="CertificationProgress">
<attr name="textSize" format="dimension" />
<attr name="textColor" format="color" />
<attr name="baseLineColor" format="color" />
<attr name="stepCount" format="integer" />
<attr name="stepTextContent" format="string" />
</declare-styleable>


</resources>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
code


/**
* @author :朱海龙
* @date :Created in 2019-06-21 15:19
* @description:关于认证进度等
* @modified By:
* @version:
*/
public class CertificationProgress extends View {

/**
* 字体默认大小
*/
public static final int defaultTextSize = 30;
/**
* 字体默认颜色
*/
public static final int defaultTextColor = Color.BLACK;
/**
* 基线默认颜色
*/
public static final int defaultBaseLineColor = Color.WHITE;

/**
* 默认操作流程步骤数量
*/
public static final int defaultStepCount = 6;

/**
* 文字画笔
*/
private TextPaint mTextPaint;
/**
* 文字大小
*/
private int textSize;
/**
* 文字颜色
*/
private int textColor;

/**
* 文字高度
*/
private int textHeight;

/**
* 基线颜色
*/
private int baseLineColor;

/**
* 通用画笔
*/
private Paint mPaint;

/**
* 流程完成提示图
*/
private Bitmap certification_finish_img;
/**
* 流程进行中提示图
*/
private Bitmap certification_ing_img;
/**
* 流程未完成提示图
*/
private Bitmap certification_not_finish_img;

/**
* maxImgYRadio : 图片中Y轴方向最大半径
* maxImgXRadio : 图片中X轴方向最大半径
*/
private int maxImgYRadio, maxImgXRadio;

/**
* 当前step,流程的完成度
*/
@Size(min = 0)
private int step = 0;

/**
* 流程步骤总数
*/
private int stepCount;

/**
* 流程步骤
*/
private List<String> stepTextContent;

/**
* 流程步骤文字长度
*/
private List<Float> stepTextLength;

public CertificationProgress(Context context) {
super(context);
init(context, null, 0);
}

public CertificationProgress(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}

public CertificationProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}

public void init(Context context, AttributeSet attrs, int defStyleAttr) {

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CertificationProgress);
textSize = (int) typedArray.getDimension(R.styleable.CertificationProgress_textSize, defaultTextSize);
textColor = typedArray.getColor(R.styleable.CertificationProgress_textColor, defaultTextColor);
baseLineColor = typedArray.getColor(R.styleable.CertificationProgress_baseLineColor, defaultBaseLineColor);
stepCount = typedArray.getInteger(R.styleable.CertificationProgress_stepCount, defaultStepCount);
CharSequence[] textArray = typedArray.getTextArray(R.styleable.CertificationProgress_stepTextContent);
typedArray.recycle();

mPaint = new Paint();
mTextPaint = new TextPaint();
mTextPaint.setTextSize(textSize);

stepTextContent = new ArrayList<>();
stepTextLength = new ArrayList<>();

Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
textHeight = (int) (fontMetrics.bottom - fontMetrics.top);

if (textArray == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
IntStream.rangeClosed(1, stepCount)
.forEach(value -> {
stepTextContent.add("Step " + value);
stepTextLength.add(mTextPaint.measureText("Step " + value));
});
} else {
for (int i = 1; i <= stepCount; i++) {
stepTextContent.add("Step " + i);
stepTextLength.add(mTextPaint.measureText("Step " + i));
}
}

} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
IntStream.range(0, stepCount)
.forEach(value -> {
stepTextContent.add(textArray[value].toString());
stepTextLength.add(mTextPaint.measureText(textArray[value].toString()));
});
} else {
for (int i = 0; i < stepCount; i++) {
stepTextContent.add(textArray[i].toString());
stepTextLength.add(mTextPaint.measureText(textArray[i].toString()));
}
}
}

certification_finish_img = BitmapFactory.decodeResource(getResources(), R.drawable.certification_finish);
certification_ing_img = BitmapFactory.decodeResource(getResources(), R.drawable.certification_ing);
certification_not_finish_img = BitmapFactory.decodeResource(getResources(), R.drawable.certification_not_finish);
maxImgYRadio = Math.max(certification_ing_img.getHeight(), Math.max(certification_finish_img.getHeight(), certification_not_finish_img.getHeight())) >> 1;
maxImgXRadio = Math.max(certification_ing_img.getWidth(), Math.max(certification_not_finish_img.getWidth(), certification_finish_img.getWidth())) >> 1;
}


@Override
protected synchronized void onDraw(Canvas canvas) {
int w = getWidth() - getPaddingLeft() - getPaddingRight() - maxImgXRadio * 2;
int h = getHeight() - getPaddingTop() - getPaddingBottom();
canvas.translate(getPaddingLeft() + maxImgXRadio, getPaddingTop());
drawBaseLine(w, h, canvas);
drawStepStateImg(canvas, w, h);
drawStepText(w, h, canvas);
}

/**
* 绘制流程对应的状态图
* @param canvas
* @param w
* @param h
*/
private void drawStepStateImg(Canvas canvas, int w, int h) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
IntStream.rangeClosed(1, stepCount)
.forEach(value -> {
if (step < value) {
if (step == (value - 1)) {
canvas.drawBitmap(certification_ing_img, w * 1f * (value - 1) / (stepCount - 1) - maxImgXRadio, completeTop(h, certification_ing_img), mPaint);
} else {
canvas.drawBitmap(certification_not_finish_img, w * 1f * (value - 1) / (stepCount - 1) - certification_not_finish_img.getWidth() / 2.0f, completeTop(h, certification_not_finish_img), mPaint);
}
} else {
canvas.drawBitmap(certification_ing_img, w * 1f * (value - 1) / (stepCount - 1) - maxImgXRadio, completeTop(h, certification_ing_img), mPaint);
canvas.drawBitmap(certification_finish_img, w * 1f * (value - 1) / (stepCount - 1) - certification_finish_img.getWidth() / 2.0f, completeTop(h, certification_finish_img), mPaint);
}
});
} else {
for (int i = 1; i <= stepCount; i++) {
if (step < i) {
if (step == (i - 1)) {
canvas.drawBitmap(certification_ing_img, w * 1f * (i - 1) / (stepCount - 1) - maxImgXRadio, completeTop(h, certification_ing_img), mPaint);
} else {
canvas.drawBitmap(certification_not_finish_img, w * 1f * (i - 1) / (stepCount - 1) - certification_not_finish_img.getWidth() / 2.0f, completeTop(h, certification_not_finish_img), mPaint);
}
} else {
canvas.drawBitmap(certification_ing_img, w * 1f * (i - 1) / (stepCount - 1) - maxImgXRadio, completeTop(h, certification_ing_img), mPaint);
canvas.drawBitmap(certification_finish_img, w * 1f * (i - 1) / (stepCount - 1) - certification_finish_img.getWidth() / 2.0f, completeTop(h, certification_finish_img), mPaint);
}
}
}
}


/**
* 绘制流程文字
* @param w
* @param h
* @param canvas
*/
private void drawStepText(int w, int h, Canvas canvas) {
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
mTextPaint.setColor(textColor);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
IntStream.range(0, stepTextContent.size())
.forEach(value -> canvas.drawText(stepTextContent.get(value), value * 1.0f * w / (stepCount - 1) - stepTextLength.get(value) / 2.0f, textHeight * 3 / 2.0f - fontMetrics.bottom, mTextPaint));
} else {
for (int i = 0; i < stepTextContent.size(); i++) {
canvas.drawText(stepTextContent.get(i), i * 1.0f * w / (stepCount - 1) - stepTextLength.get(i) / 2.0f, textHeight * 3 / 2.0f - fontMetrics.bottom, mTextPaint);
}
}
}

/**
* 绘制baseline
* @param w
* @param h
* @param canvas
*/
private void drawBaseLine(int w, int h, Canvas canvas) {
mPaint.reset();
mPaint.setColor(baseLineColor);
canvas.drawLine(0, completeTop(h, null), w, completeTop(h, null), mPaint);
mPaint.setStrokeWidth(10);
canvas.drawLine(0, completeTop(h, null), w * step * 1f / (stepCount - (step < stepCount ? 1 : 0)), completeTop(h, null), mPaint);
mPaint.reset();
}

/**
* 计算top距离
* @param h
* @param bitmap
* @return
*/
private float completeTop(int h, Bitmap bitmap) {
return (h + textHeight * 2 - (bitmap == null ? 0 : bitmap.getHeight())) / 2.0f;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int setWidth, setHeight;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();

if (widthMode == MeasureSpec.EXACTLY) {
setWidth = measureWidth;
} else {
setWidth = displayMetrics.widthPixels;
}

int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
setHeight = measureHeight;
} else {
int h = textHeight * 2 + (maxImgYRadio << 1) + getPaddingTop() + getPaddingBottom();
setHeight = Math.min(h, measureHeight);
}
setMeasuredDimension(setWidth, setHeight);
}

/**
* 设置流程的完成度
* @param step
*/
public synchronized void setStep(int step) {
if (step > stepCount || step < 0) {
throw new IllegalArgumentException("超出步骤范围");
}
this.step = step;
postInvalidate();
}

/**
* 动态设置流程步骤
* @param paramList
*/
public synchronized void setStepTextContent(@NonNull List<String> paramList) {
this.stepCount = paramList.size();
if (stepCount < 2) {
throw new IllegalArgumentException("参数长度异常,长度至少为2");
}
stepTextContent.clear();
stepTextLength.clear();
this.stepTextContent.addAll(paramList);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
IntStream.range(0, stepCount)
.forEach(value ->
stepTextLength.add(mTextPaint.measureText(stepTextContent.get(value)))
);
} else {
for (int i = 0; i < stepCount; i++) {
stepTextLength.add(mTextPaint.measureText(stepTextContent.get(i)));
}
}
postInvalidate(http://www.amjmh.com/v/BIBRGZ_558768/);
}
}
--------------------- 

posted @ 2019-08-03 19:23  李艳艳665  阅读(255)  评论(0编辑  收藏  举报