Kevin Learn Android:流程指示器(一)
2021-07-20 本文已影响0人
Kevin_小飞象
每日一图.jpg
水平流程指示器
效果图
01.png代码
1. 数据
/**
* Created on 2021/7/19 13:57
*
* @author Gong Youqiang
*/
public class StepBean {
public static final int STEP_UNDO = -1;//未完成 undo step
public static final int STEP_CURRENT = 0;//正在进行 current step
public static final int STEP_COMPLETED = 1;//已完成 completed step
private String name;
private int state;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getState()
{
return state;
}
public void setState(int state)
{
this.state = state;
}
public StepBean()
{
}
public StepBean(String name, int state)
{
this.name = name;
this.state = state;
}
}
2. 自定义水平指示器 HorizontalStepsViewIndicator.java
/**
* Created on 2021/7/19 13:58
*
* @author Gong Youqiang
*/
public class HorizontalStepsViewIndicator extends View {
//定义默认的高度 definition default height
private int defaultStepIndicatorNum = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, getResources().getDisplayMetrics());
private float mCompletedLineHeight;//完成线的高度 definition completed line height
private float mCircleRadius;//圆的半径 definition circle radius
private Drawable mCompleteIcon;//完成的默认图片 definition default completed icon
private Drawable mAttentionIcon;//正在进行的默认图片 definition default underway icon
private Drawable mDefaultIcon;//默认的背景图 definition default unCompleted icon
private float mCenterY;//该view的Y轴中间位置 definition view centerY position
private float mLeftY;//左上方的Y位置 definition rectangle LeftY position
private float mRightY;//右下方的位置 definition rectangle RightY position
private List<StepBean> mStepBeanList ;//当前有几部流程 there are currently few step
private int mStepNum = 0;
private float mLinePadding;//两条连线之间的间距 definition the spacing between the two circles
private List<Float> mCircleCenterPointPositionList;//定义所有圆的圆心点位置的集合 definition all of circles center point list
private Paint mUnCompletedPaint;//未完成Paint definition mUnCompletedPaint
private Paint mCompletedPaint;//完成paint definition mCompletedPaint
private int mUnCompletedLineColor = ContextCompat.getColor(getContext(), R.color.uncompleted_color);//定义默认未完成线的颜色 definition
private int mCompletedLineColor = Color.WHITE;//定义默认完成线的颜色 definition mCompletedLineColor
private PathEffect mEffects;
private int mComplectingPosition;//正在进行position underway position
private Path mPath;
private OnDrawIndicatorListener mOnDrawListener;
private int screenWidth;//this screen width
/**
* 设置监听
*
* @param onDrawListener
*/
public void setOnDrawListener(OnDrawIndicatorListener onDrawListener)
{
mOnDrawListener = onDrawListener;
}
/**
* get圆的半径 get circle radius
*
* @return
*/
public float getCircleRadius()
{
return mCircleRadius;
}
public HorizontalStepsViewIndicator(Context context)
{
this(context, null);
}
public HorizontalStepsViewIndicator(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public HorizontalStepsViewIndicator(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
/**
* init
*/
private void init()
{
mStepBeanList = new ArrayList<>();
mPath = new Path();
mEffects = new DashPathEffect(new float[]{8, 8, 8, 8}, 1);
mCircleCenterPointPositionList = new ArrayList<>();//初始化
mUnCompletedPaint = new Paint();
mCompletedPaint = new Paint();
mUnCompletedPaint.setAntiAlias(true);
mUnCompletedPaint.setColor(mUnCompletedLineColor);
mUnCompletedPaint.setStyle(Paint.Style.STROKE);
mUnCompletedPaint.setStrokeWidth(2);
mCompletedPaint.setAntiAlias(true);
mCompletedPaint.setColor(mCompletedLineColor);
mCompletedPaint.setStyle(Paint.Style.STROKE);
mCompletedPaint.setStrokeWidth(2);
mUnCompletedPaint.setPathEffect(mEffects);
mCompletedPaint.setStyle(Paint.Style.FILL);
//已经完成线的宽高 set mCompletedLineHeight
mCompletedLineHeight = 0.05f * defaultStepIndicatorNum;
//圆的半径 set mCircleRadius
mCircleRadius = 0.28f * defaultStepIndicatorNum;
//线与线之间的间距 set mLinePadding
mLinePadding = 0.85f * defaultStepIndicatorNum;
mCompleteIcon = ContextCompat.getDrawable(getContext(), R.mipmap.complted);//已经完成的icon
mAttentionIcon = ContextCompat.getDrawable(getContext(), R.mipmap.attention);//正在进行的icon
mDefaultIcon = ContextCompat.getDrawable(getContext(), R.mipmap.default_icon);//未完成的icon
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = defaultStepIndicatorNum * 2;
if(MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(widthMeasureSpec))
{
screenWidth = MeasureSpec.getSize(widthMeasureSpec);
}
int height = defaultStepIndicatorNum;
if(MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(heightMeasureSpec))
{
height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec));
}
width = (int) (mStepNum * mCircleRadius * 2 - (mStepNum - 1) * mLinePadding);
setMeasuredDimension(width, height);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
//获取中间的高度,目的是为了让该view绘制的线和圆在该view垂直居中 get view centerY,keep current stepview center vertical
mCenterY = 0.5f * getHeight();
//获取左上方Y的位置,获取该点的意义是为了方便画矩形左上的Y位置
mLeftY = mCenterY - (mCompletedLineHeight / 2);
//获取右下方Y的位置,获取该点的意义是为了方便画矩形右下的Y位置
mRightY = mCenterY + mCompletedLineHeight / 2;
mCircleCenterPointPositionList.clear();
for(int i = 0; i < mStepNum; i++)
{
//先计算全部最左边的padding值(getWidth()-(圆形直径+两圆之间距离)*2)
float paddingLeft = (screenWidth - mStepNum * mCircleRadius * 2 - (mStepNum - 1) * mLinePadding) / 2;
//add to list
mCircleCenterPointPositionList.add(paddingLeft + mCircleRadius + i * mCircleRadius * 2 + i * mLinePadding);
}
/**
* set listener
*/
if(mOnDrawListener!=null)
{
mOnDrawListener.ondrawIndicator();
}
}
@Override
protected synchronized void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if(mOnDrawListener!=null)
{
mOnDrawListener.ondrawIndicator();
}
mUnCompletedPaint.setColor(mUnCompletedLineColor);
mCompletedPaint.setColor(mCompletedLineColor);
//-----------------------画线-------draw line-----------------------------------------------
for(int i = 0; i < mCircleCenterPointPositionList.size() -1; i++)
{
//前一个ComplectedXPosition
final float preComplectedXPosition = mCircleCenterPointPositionList.get(i);
//后一个ComplectedXPosition
final float afterComplectedXPosition = mCircleCenterPointPositionList.get(i + 1);
if(i <= mComplectingPosition&&mStepBeanList.get(0).getState()!=StepBean.STEP_UNDO)//判断在完成之前的所有点
{
//判断在完成之前的所有点,画完成的线,这里是矩形,很细的矩形,类似线,为了做区分,好看些
canvas.drawRect(preComplectedXPosition + mCircleRadius - 10, mLeftY, afterComplectedXPosition - mCircleRadius + 10, mRightY, mCompletedPaint);
} else
{
mPath.moveTo(preComplectedXPosition + mCircleRadius, mCenterY);
mPath.lineTo(afterComplectedXPosition - mCircleRadius, mCenterY);
canvas.drawPath(mPath, mUnCompletedPaint);
}
}
//-----------------------画线-------draw line-----------------------------------------------
//-----------------------画图标-----draw icon-----------------------------------------------
for(int i = 0; i < mCircleCenterPointPositionList.size(); i++)
{
final float currentComplectedXPosition = mCircleCenterPointPositionList.get(i);
Rect rect = new Rect((int) (currentComplectedXPosition - mCircleRadius), (int) (mCenterY - mCircleRadius), (int) (currentComplectedXPosition + mCircleRadius), (int) (mCenterY + mCircleRadius));
StepBean stepsBean = mStepBeanList.get(i);
if(stepsBean.getState()==StepBean.STEP_UNDO)
{
mDefaultIcon.setBounds(rect);
mDefaultIcon.draw(canvas);
}else if(stepsBean.getState()==StepBean.STEP_CURRENT)
{
mCompletedPaint.setColor(Color.WHITE);
canvas.drawCircle(currentComplectedXPosition, mCenterY, mCircleRadius * 1.1f, mCompletedPaint);
mAttentionIcon.setBounds(rect);
mAttentionIcon.draw(canvas);
}else if(stepsBean.getState()==StepBean.STEP_COMPLETED)
{
mCompleteIcon.setBounds(rect);
mCompleteIcon.draw(canvas);
}
}
//-----------------------画图标-----draw icon-----------------------------------------------
}
/**
* 得到所有圆点所在的位置
*
* @return
*/
public List<Float> getCircleCenterPointPositionList()
{
return mCircleCenterPointPositionList;
}
/**
* 设置流程步数
*
* @param stepsBeanList 流程步数
*/
public void setStepNum(List<StepBean> stepsBeanList)
{
this.mStepBeanList = stepsBeanList;
mStepNum = mStepBeanList.size();
if(mStepBeanList!=null&&mStepBeanList.size()>0)
{
for(int i = 0;i<mStepNum;i++)
{
StepBean stepsBean = mStepBeanList.get(i);
{
if(stepsBean.getState()==StepBean.STEP_COMPLETED)
{
mComplectingPosition = i;
}
}
}
}
requestLayout();
}
/**
* 设置未完成线的颜色
*
* @param unCompletedLineColor
*/
public void setUnCompletedLineColor(int unCompletedLineColor)
{
this.mUnCompletedLineColor = unCompletedLineColor;
}
/**
* 设置已完成线的颜色
*
* @param completedLineColor
*/
public void setCompletedLineColor(int completedLineColor)
{
this.mCompletedLineColor = completedLineColor;
}
/**
* 设置默认图片
*
* @param defaultIcon
*/
public void setDefaultIcon(Drawable defaultIcon)
{
this.mDefaultIcon = defaultIcon;
}
/**
* 设置已完成图片
*
* @param completeIcon
*/
public void setCompleteIcon(Drawable completeIcon)
{
this.mCompleteIcon = completeIcon;
}
/**
* 设置正在进行中的图片
*
* @param attentionIcon
*/
public void setAttentionIcon(Drawable attentionIcon)
{
this.mAttentionIcon = attentionIcon;
}
/**
* 设置对view监听
*/
public interface OnDrawIndicatorListener
{
void ondrawIndicator();
}
}
3. HorizontalStepView.java
/**
* Created on 2021/7/19 14:01
*
* @author Gong Youqiang
*/
public class HorizontalStepView extends LinearLayout implements HorizontalStepsViewIndicator.OnDrawIndicatorListener {
private RelativeLayout mTextContainer;
private HorizontalStepsViewIndicator mStepsViewIndicator;
private List<StepBean> mStepBeanList;
private int mComplectingPosition;
private int mUnComplectedTextColor = ContextCompat.getColor(getContext(), R.color.uncompleted_text_color);//定义默认未完成文字的颜色;
private int mComplectedTextColor = ContextCompat.getColor(getContext(), android.R.color.white);//定义默认完成文字的颜色;
private int mTextSize = 14;//default textSize
private TextView mTextView;
public HorizontalStepView(Context context)
{
this(context, null);
}
public HorizontalStepView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public HorizontalStepView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
init();
}
private void init()
{
View rootView = LayoutInflater.from(getContext()).inflate(R.layout.widget_horizontal_stepsview, this);
mStepsViewIndicator = (HorizontalStepsViewIndicator) rootView.findViewById(R.id.steps_indicator);
mStepsViewIndicator.setOnDrawListener(this);
mTextContainer = (RelativeLayout) rootView.findViewById(R.id.rl_text_container);
}
/**
* 设置显示的文字
*
* @param stepsBeanList
* @return
*/
public HorizontalStepView setStepViewTexts(List<StepBean> stepsBeanList)
{
mStepBeanList = stepsBeanList;
mStepsViewIndicator.setStepNum(mStepBeanList);
return this;
}
/**
* 设置未完成文字的颜色
*
* @param unComplectedTextColor
* @return
*/
public HorizontalStepView setStepViewUnComplectedTextColor(int unComplectedTextColor)
{
mUnComplectedTextColor = unComplectedTextColor;
return this;
}
/**
* 设置完成文字的颜色
*
* @param complectedTextColor
* @return
*/
public HorizontalStepView setStepViewComplectedTextColor(int complectedTextColor)
{
this.mComplectedTextColor = complectedTextColor;
return this;
}
/**
* 设置StepsViewIndicator未完成线的颜色
*
* @param unCompletedLineColor
* @return
*/
public HorizontalStepView setStepsViewIndicatorUnCompletedLineColor(int unCompletedLineColor)
{
mStepsViewIndicator.setUnCompletedLineColor(unCompletedLineColor);
return this;
}
/**
* 设置StepsViewIndicator完成线的颜色
*
* @param completedLineColor
* @return
*/
public HorizontalStepView setStepsViewIndicatorCompletedLineColor(int completedLineColor)
{
mStepsViewIndicator.setCompletedLineColor(completedLineColor);
return this;
}
/**
* 设置StepsViewIndicator默认图片
*
* @param defaultIcon
*/
public HorizontalStepView setStepsViewIndicatorDefaultIcon(Drawable defaultIcon)
{
mStepsViewIndicator.setDefaultIcon(defaultIcon);
return this;
}
/**
* 设置StepsViewIndicator已完成图片
*
* @param completeIcon
*/
public HorizontalStepView setStepsViewIndicatorCompleteIcon(Drawable completeIcon)
{
mStepsViewIndicator.setCompleteIcon(completeIcon);
return this;
}
/**
* 设置StepsViewIndicator正在进行中的图片
*
* @param attentionIcon
*/
public HorizontalStepView setStepsViewIndicatorAttentionIcon(Drawable attentionIcon)
{
mStepsViewIndicator.setAttentionIcon(attentionIcon);
return this;
}
/**
* set textSize
*
* @param textSize
* @return
*/
public HorizontalStepView setTextSize(int textSize)
{
if(textSize > 0)
{
mTextSize = textSize;
}
return this;
}
@Override
public void ondrawIndicator()
{
if(mTextContainer != null)
{
mTextContainer.removeAllViews();
List<Float> complectedXPosition = mStepsViewIndicator.getCircleCenterPointPositionList();
if(mStepBeanList != null && complectedXPosition != null && complectedXPosition.size() > 0)
{
for(int i = 0; i < mStepBeanList.size(); i++)
{
mTextView = new TextView(getContext());
mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSize);
mTextView.setText(mStepBeanList.get(i).getName());
int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
mTextView.measure(spec, spec);
// getMeasuredWidth
int measuredWidth = mTextView.getMeasuredWidth();
mTextView.setX(complectedXPosition.get(i) - measuredWidth / 2);
mTextView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
if(i <= mComplectingPosition)
{
mTextView.setTypeface(null, Typeface.BOLD);
mTextView.setTextColor(mComplectedTextColor);
} else
{
mTextView.setTextColor(mUnComplectedTextColor);
}
mTextContainer.addView(mTextView);
}
}
}
}
}
4. 使用
布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary">
<com.hk.launcherdemo.widget.stepview.HorizontalStepView
android:id="@+id/stepView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn_status"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@color/colorPrimary"
android:clickable="true"
android:gravity="center"
android:padding="16dp"
android:text="click horizontalStepview"
android:textAllCaps="true"
android:textAppearance="@style/TextAppearance.AppCompat.Button"
android:textColor="@android:color/white"
android:textSize="18sp"/>
</RelativeLayout>
代码逻辑
public class StepViewActivity extends BaseActivity {
@BindView(R.id.stepView)
HorizontalStepView mStepView;
@BindView(R.id.btn_status)
Button mButton;
private List<StepBean> stepsBeanList;
@Override
public int getLayoutId() {
return R.layout.activity_step_view;
}
@Override
public void initView() {
initData();
}
private void initData() {
stepsBeanList = new ArrayList<>();
StepBean stepBean0 = new StepBean("接单",1);
StepBean stepBean1 = new StepBean("打包",1);
StepBean stepBean2 = new StepBean("出发",1);
StepBean stepBean3 = new StepBean("送单",1);
StepBean stepBean4 = new StepBean("完成",0);
StepBean stepBean5 = new StepBean("支付",-1);
stepsBeanList.add(stepBean0);
stepsBeanList.add(stepBean1);
stepsBeanList.add(stepBean2);
stepsBeanList.add(stepBean3);
stepsBeanList.add(stepBean4);
stepsBeanList.add(stepBean5);
}
@OnClick({R.id.btn_status})
public void click(View view) {
mStepView.setStepViewTexts(stepsBeanList)
.setTextSize(16)//set textSize
.setStepsViewIndicatorCompletedLineColor(ContextCompat.getColor(getBaseContext(), android.R.color.white))//设置StepsViewIndicator完成线的颜色
.setStepsViewIndicatorUnCompletedLineColor(ContextCompat.getColor(getBaseContext(), R.color.uncompleted_text_color))//设置StepsViewIndicator未完成线的颜色
.setStepViewComplectedTextColor(ContextCompat.getColor(getBaseContext(), android.R.color.white))//设置StepsView text完成线的颜色
.setStepViewUnComplectedTextColor(ContextCompat.getColor(getBaseContext(), R.color.uncompleted_text_color))//设置StepsView text未完成线的颜色
.setStepsViewIndicatorCompleteIcon(ContextCompat.getDrawable(getBaseContext(), R.mipmap.complted))//设置StepsViewIndicator CompleteIcon
.setStepsViewIndicatorDefaultIcon(ContextCompat.getDrawable(getBaseContext(), R.mipmap.default_icon))//设置StepsViewIndicator DefaultIcon
.setStepsViewIndicatorAttentionIcon(ContextCompat.getDrawable(getBaseContext(), R.mipmap.attention));//设置StepsViewIndicator AttentionIcon
}
}