1、MyStepInfoBean.java
每个节点样式
package com.dj.processindication.StepView;
public class MyStepInfoBean {
private String name;
private Enum status;
public MyStepInfoBean(String name, Enum status) {
this.name = name;
this.status = status;
}
public enum StepStatus {
COMPLETED,UNCOMPLETED,COMPLETING
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Enum getStatus() {
return status;
}
public void setStatus(Enum status) {
this.status = status;
}
}
2、StepView.java
绘制所有节点
package com.dj.processindication.StepView;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.dj.processindication.R;
import java.util.ArrayList;
import java.util.List;
public class StepView extends View {
private static final int DEFAULT_RADIU = 35;
private static final int DEFAULT_LINE_HEIGHT = 120;
private static final int DEFAULT_DASH_PADDING = 6;
private static final int DEFAULT_DASH_HEIGHT = 15;
private static final int ORIENTATION_VERTICAL = 0;
private static final int ORIENTATION_HORIZONTAL = 1;
private static final int DEFAULT_COMPLETED_DRAWABLE_ID = R.drawable.circledone;
private static final int DEFAULT_UNCOMPLETED_DRAWABLE_ID = R.drawable.circlenotdo;
private static final int DEFAULT_COMPLETING_DRAWABLE_ID = R.drawable.circledoing;
private int mRadiu;
private int mLineLength;
private int mDashPadding;
private int mDashLength;
private int mOrientation;
private int mCompletedDrawableResourceId;
private int mUncompletedDrawableResourceId;
private int mCompletingDrawableResourceId;
private Bitmap mIconCompleted;
private Bitmap mIconCompleting;
private Bitmap mIconUncompleted;
private Paint mCompletePaint;
private Paint mUnCompleted;
private List<MyStepInfoBean> mData = new ArrayList<>();
private int mWidth;
private int mHeight;
private Rect mCheckRect;
private Rect mExclamationMarkRect;
private Rect mCircleRect;
private Paint mIconPaint;
public StepView(Context context) {
this(context, null);
}
public StepView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public StepView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.StepView);
mRadiu = typedArray.getInt(R.styleable.StepView_radius, DEFAULT_RADIU);
mLineLength = typedArray.getInt(R.styleable.StepView_line_height, DEFAULT_LINE_HEIGHT);
mDashPadding = typedArray.getInt(R.styleable.StepView_dash_padding, DEFAULT_DASH_PADDING);
mDashLength = typedArray.getInt(R.styleable.StepView_dash_height, DEFAULT_DASH_HEIGHT);
mOrientation = typedArray.getInt(R.styleable.StepView_orientation, ORIENTATION_HORIZONTAL);
mCompletedDrawableResourceId = typedArray.getResourceId(R.styleable.StepView_icon_completed,DEFAULT_COMPLETED_DRAWABLE_ID);
mUncompletedDrawableResourceId = typedArray.getResourceId(R.styleable.StepView_icon_uncompleted,DEFAULT_UNCOMPLETED_DRAWABLE_ID);
mCompletingDrawableResourceId = typedArray.getResourceId(R.styleable.StepView_icon_completing,DEFAULT_COMPLETING_DRAWABLE_ID);
typedArray.recycle();
init();
}
private void init() {
mIconCompleted = BitmapFactory.decodeResource(getResources(), mCompletedDrawableResourceId);
mIconCompleting = BitmapFactory.decodeResource(getResources(), mCompletingDrawableResourceId);
mIconUncompleted = BitmapFactory.decodeResource(getResources(), mUncompletedDrawableResourceId);
mIconPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mIconPaint.setStyle(Paint.Style.FILL);
mCompletePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCompletePaint.setColor(0xFF106382);
mCompletePaint.setStrokeWidth(5);
mCompletePaint.setTextSize(30);
mUnCompleted = new Paint(Paint.ANTI_ALIAS_FLAG);
mUnCompleted.setColor(0xFFdbdbdb);
mUnCompleted.setStrokeWidth(5);
mCheckRect = new Rect(0, 0, mIconCompleted.getWidth(), mIconCompleted.getHeight());
mExclamationMarkRect = new Rect(0, 0, mIconCompleting.getWidth(), mIconCompleting.getHeight());
mCircleRect = new Rect(0, 0, mIconUncompleted.getWidth(), mIconUncompleted.getHeight());
}
public void setData(List<MyStepInfoBean> data) {
if (data == null || data.size() == 0) {
return;
}
mData = data;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mData == null || mData.size() == 0) {
return;
}
int centerIndex = mData.size() % 2 != 0 ? (int) Math.ceil(mData.size() / 2.0f) - 1 : mData.size() / 2 - 1;
for (int i = 0; i < mData.size(); i++) {
MyStepInfoBean item = mData.get(i);
int centerX = (mOrientation == ORIENTATION_HORIZONTAL ? mWidth : mHeight) / 2;
int centerY = (mOrientation == ORIENTATION_HORIZONTAL ? mHeight : mWidth) / 2;
int bitmapCenter = mData.size() % 2 != 0 ? centerX - (centerIndex - i) * (mLineLength + mRadiu * 2) : (int) (centerX - (centerIndex - i + 0.5) * (mLineLength + mRadiu * 2));
Rect srcBitmapRect = mOrientation == ORIENTATION_HORIZONTAL ? new Rect(bitmapCenter - mRadiu, centerY - mRadiu, bitmapCenter + mRadiu, centerY + mRadiu) :
new Rect(centerY - mRadiu, bitmapCenter - mRadiu, centerY + mRadiu, bitmapCenter + mRadiu);
canvas.drawBitmap(item.getStatus() == MyStepInfoBean.StepStatus.COMPLETED ? mIconCompleted :
item.getStatus() == MyStepInfoBean.StepStatus.COMPLETING ? mIconCompleting :
mIconUncompleted, item.getStatus() == MyStepInfoBean.StepStatus.COMPLETED ? mCheckRect :
item.getStatus() == MyStepInfoBean.StepStatus.COMPLETING ? mExclamationMarkRect :
mCircleRect, srcBitmapRect, mIconPaint);
float v = mCompletePaint.measureText(item.getName());
if (mOrientation == ORIENTATION_HORIZONTAL) {
canvas.drawText(item.getName(), bitmapCenter - v / 2, centerY + mRadiu * 2, mCompletePaint);
} else {
canvas.drawText(item.getName(), centerY + mRadiu * 2, bitmapCenter, mCompletePaint);
}
if (i < mData.size() - 1) {
int lineLeft = mData.size() % 2 != 0 ? (int) (centerX - (centerIndex - i) * mLineLength - (centerIndex - i - 0.5) * mRadiu * 2) : (int) (centerX - (centerIndex - i + 0.5) * mLineLength - (centerIndex - i) * mRadiu * 2);
if (mData.get(i + 1).getStatus() == MyStepInfoBean.StepStatus.UNCOMPLETED) {
for (int j = 0; j < 6; j++) {
if (mOrientation == ORIENTATION_HORIZONTAL) {
canvas.drawLine(lineLeft + (mDashLength + mDashPadding) * j, centerY - 2, lineLeft + mDashLength * (j + 1) + mDashPadding * j, centerY - 2, mUnCompleted);
} else {
canvas.drawLine(centerY - 2, lineLeft + (mDashLength + mDashPadding) * j, centerY - 2, lineLeft + mDashLength * (j + 1) + mDashPadding * j, mUnCompleted);
}
}
} else {
if (mOrientation == ORIENTATION_HORIZONTAL) {
canvas.drawLine(lineLeft, centerY , lineLeft + mLineLength, centerY , mCompletePaint);
} else {
canvas.drawLine(centerY - 2, lineLeft, centerY - 2, lineLeft + mLineLength, mCompletePaint);
}
}
}
}
}
}
3、CurrentState.java
业务层面的工具类
package com.dj.processindication.StepView;
import java.util.ArrayList;
public class CurrentState {
private ArrayList<MyStepInfoBean> mCurrentStep = new ArrayList<>();
private StepView mStepView;
public CurrentState(StepView stepView) {
this.mStepView = stepView;
initData();
}
private void initData() {
setStepViewNone();
}
public void setCurrentState(int i){
switch(i){
case 0:
setStepView0();
break;
case 1:
setStepView1();
break;
case 2:
setStepView2();
break;
case 3:
setStepView3();
break;
case 4:
setStepView4();
break;
}
}
private void setData() {
mStepView.setData(mCurrentStep);
}
private void setStepViewNone(){
mCurrentStep.clear();
mCurrentStep.add(new MyStepInfoBean("步骤1",MyStepInfoBean.StepStatus.UNCOMPLETED));//0
mCurrentStep.add(new MyStepInfoBean("步骤2",MyStepInfoBean.StepStatus.UNCOMPLETED));//1
mCurrentStep.add(new MyStepInfoBean("步骤3",MyStepInfoBean.StepStatus.UNCOMPLETED));//2
mCurrentStep.add(new MyStepInfoBean("步骤4",MyStepInfoBean.StepStatus.UNCOMPLETED));//3
mCurrentStep.add(new MyStepInfoBean("步骤5",MyStepInfoBean.StepStatus.UNCOMPLETED));//4
setData();
}
private void setStepView0(){
mCurrentStep.clear();
mCurrentStep.add(new MyStepInfoBean("步骤1",MyStepInfoBean.StepStatus.COMPLETED));//0
mCurrentStep.add(new MyStepInfoBean("步骤2",MyStepInfoBean.StepStatus.UNCOMPLETED));//1
mCurrentStep.add(new MyStepInfoBean("步骤3",MyStepInfoBean.StepStatus.UNCOMPLETED));//2
mCurrentStep.add(new MyStepInfoBean("步骤4",MyStepInfoBean.StepStatus.UNCOMPLETED));//3
mCurrentStep.add(new MyStepInfoBean("步骤5",MyStepInfoBean.StepStatus.UNCOMPLETED));//4
setData();
}
}
4、activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<com.dj.processindication.StepView.StepView
android:id="@+id/sv_currentState"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:icon_completed="@drawable/circledone"
app:icon_uncompleted="@drawable/circlenotdo"
app:icon_completing="@drawable/circledoing"
/>
</LinearLayout>
</LinearLayout>
5、attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="StepView">
<attr name="radius" format="integer"/>
<attr name="line_height" format="integer"/>
<attr name="dash_padding" format="integer"/>
<attr name="dash_height" format="integer"/>
<attr name="orientation">
<enum name="vertical" value="0"/>
<enum name="horizontal" value="1"/>
</attr>
<attr name="icon_completed" format="reference"/>
<attr name="icon_uncompleted" format="reference"/>
<attr name="icon_completing" format="reference"/>
</declare-styleable>
</resources>
6、MainActivity
package com.dj.processindication;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.dj.processindication.StepView.CurrentState;
import com.dj.processindication.StepView.StepView;
public class MainActivity extends AppCompatActivity {
private StepView mStepView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStepView = (StepView) findViewById(R.id.sv_currentState);
CurrentState mCurrentState = new CurrentState(mStepView);
mCurrentState.setCurrentState(2);
}
}