完整代碼

自定義屬性xml文件canvas


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


<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>post


</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 {ui

/**
* 字體默認大小
*/
public static final int defaultTextSize = 30;
/**
* 字體默認顏色
*/
public static final int defaultTextColor = Color.BLACK;
/**
* 基線默認顏色
*/
public static final int defaultBaseLineColor = Color.WHITE;this

/**
* 默認操做流程步驟數量
*/
public static final int defaultStepCount = 6;code

/**
* 文字畫筆
*/
private TextPaint mTextPaint;
/**
* 文字大小
*/
private int textSize;
/**
* 文字顏色
*/
private int textColor;orm

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

/**
* 基線顏色
*/
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/); }}--------------------- 

相關文章
相關標籤/搜索