一、先看看效果,是不是你需要的
二 、使用方式
StepHorizontalView mStepSv = (StepHorizontalView) findViewById(R.id.sv_step);
mStepSv.setProgress(3, 4);
List<String> list = new ArrayList<>();
list.add("第一步");
list.add("第二步");
list.add("第三步");
list.add("第四步");
mStepSv.setTitles(list);
三、佈局
<com.example.zyt.mystepview.mine.StepHorizontalView
android:id="@+id/sv_step"
android:layout_width="match_parent"
android:layout_height="150dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:background="@android:color/darker_gray"
app:h_bg_color="@color/colorPrimaryDark"
app:h_bg_radius="6dp"
app:h_bg_width="4dp"
app:h_pro_color="@android:color/holo_red_light"
app:h_pro_radius="6dp"
app:h_pro_width="5dp"
app:h_max_step="5"
app:h_pro_step="2"
app:h_text_padding="30dp"
app:h_textsize="16sp" />
四、屬性講解
1. h_bg_color 默認進度條的顏色
2. h_bg_radius 默認節點的半徑大小
3. h_bg_width 默認間隔線的寬度
4. h_pro_color 已過進度條的顏色
5. h_pro_radius 已過節點的半徑大小
6. h_pro_width 已過間隔線的寬度
7. h_text_padding 進度條與文本的距離
8. h_textsize 文本的字體大小
9. h_max_step 最多節點的個數
10. h_pro_step 節點的進度
五、自定義控件
public class StepHorizontalView extends View {
private int bgWidth;
private int bgHeight;
private float bgRadius;
private float proRadius;
private float startX;
private float stopX;
private float bgCenterY;
private int lineBgWidth;
private int bgColor;
private int lineProWidth;
private int proColor;
private int textPadding;
private int maxStep;
private int textSize;
private int proStep;
private Paint bgPaint;
private Paint proPaint;
private int interval;
private List<String> titles;
private Map<String, Integer> map;
private float startLine;
private float stopLine;
public StepHorizontalView(Context context) {
this(context, null);
}
public StepHorizontalView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public StepHorizontalView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FlowViewHorizontal);
bgRadius = ta.getDimension(R.styleable.FlowViewHorizontal_h_bg_radius, 10);
proRadius = ta.getDimension(R.styleable.FlowViewHorizontal_h_pro_radius, 8);
lineBgWidth = (int) ta.getDimension(R.styleable.FlowViewHorizontal_h_bg_width, 3f);
bgColor = ta.getColor(R.styleable.FlowViewHorizontal_h_bg_color, Color.parseColor("#cccccc"));
lineProWidth = (int) ta.getDimension(R.styleable.FlowViewHorizontal_h_pro_width, 2f);
proColor = ta.getColor(R.styleable.FlowViewHorizontal_h_pro_color, Color.parseColor("#EF5350"));
textPadding = (int) ta.getDimension(R.styleable.FlowViewHorizontal_h_text_padding, 20);
maxStep = ta.getInt(R.styleable.FlowViewHorizontal_h_max_step, 6);
textSize = (int) ta.getDimension(R.styleable.FlowViewHorizontal_h_textsize, 20);
proStep = ta.getInt(R.styleable.FlowViewHorizontal_h_pro_step, 1);
ta.recycle();
initView();
}
private void initView() {
bgPaint = new Paint();
bgPaint.setAntiAlias(true); // 鋸齒
bgPaint.setStyle(Paint.Style.FILL);
bgPaint.setColor(bgColor);
bgPaint.setStrokeWidth(lineBgWidth);
bgPaint.setTextSize(textSize);
bgPaint.setTextAlign(Paint.Align.CENTER);
proPaint = new Paint();
proPaint.setAntiAlias(true);
proPaint.setStyle(Paint.Style.FILL);
proPaint.setColor(proColor);
proPaint.setStrokeWidth(lineProWidth);
proPaint.setTextSize(textSize);
proPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
bgWidth = widthSize;
}
if (heightMode == MeasureSpec.EXACTLY) {
bgHeight = heightSize;
}
interval = (int) ((bgWidth-bgRadius*2-getPaddingRight()-getPaddingLeft())/(maxStep - 1));//緊挨着的兩個圓心的距離
startLine = getPaddingLeft() + bgRadius * 2;//作爲線的起點
stopLine = getPaddingLeft() + interval * (maxStep-1);//作爲線的終點
startX = getPaddingLeft() + bgRadius;//作爲圓的起始點
stopX = stopLine + bgRadius;//作爲最後一個圓的圓心 bgWidth - bgRadius - getPaddingRight()
bgCenterY = getPaddingTop()+bgRadius;//作爲線和圓心的縱座標
}
@Override
protected void onDraw(Canvas canvas) {
drawBg(canvas);
drawProgress(canvas);
drawText(canvas);
}
/**
* 繪畫文本
* @param canvas
*/
private void drawText(Canvas canvas) {
for (int i = 0; i < maxStep; i++) {
if (i < proStep) {
if (null != titles && i < titles.size()) {
canvas.drawText(titles.get(i), startX + (i * interval), bgCenterY + textPadding + (bgRadius < proRadius ? proRadius : bgRadius), proPaint);
}
} else {
if (null != titles && i < titles.size()) {
String title = titles.get(i);
if (null == title) {
continue;
}
canvas.drawText(title, startX + (i * interval), bgCenterY + textPadding + (bgRadius < proRadius ? proRadius : bgRadius), bgPaint);
}
}
}
}
/**
* 繪畫底部默認進度條
* @param canvas
*/
private void drawBg(Canvas canvas) {
canvas.drawLine(startLine, bgCenterY, stopLine, bgCenterY, bgPaint);
for (int i = 0; i < maxStep; i++) {
canvas.drawCircle(startX + (i * interval), bgCenterY, bgRadius, bgPaint);
}
}
/**
* 繪畫進度
* @param canvas
*/
private void drawProgress(Canvas canvas) {
for (int i = 0; i < proStep; i++) {
canvas.drawCircle(startX + (i * interval), bgCenterY, proRadius, proPaint);
canvas.drawLine(startX, bgCenterY, startX + (i * interval), bgCenterY, proPaint);
}
}
/**
* 進度設置
*
* @param progress 已完成到哪部
* @param maxStep 總步驟
*/
public void setProgress(int progress, int maxStep) {
proStep = progress;
this.maxStep = maxStep;
invalidate();
}
public void setTitles(List<String> titles){
this.titles = titles;
}
}
六、在values中創建一個attrs.xml文件
<!--step view -->
<declare-styleable name="FlowViewHorizontal">
<attr name="h_bg_radius" format="dimension" />
<attr name="h_pro_radius" format="dimension" />
<attr name="h_bg_width" format="dimension" />
<attr name="h_pro_width" format="dimension" />
<attr name="h_bg_color" format="color" />
<attr name="h_pro_color" format="color" />
<attr name="h_text_padding" format="dimension" />
<attr name="h_max_step" format="integer" />
<attr name="h_textsize" format="dimension" />
<attr name="h_pro_step" format="integer" />
</declare-styleable>
七、不足之處
這個控件不能wrap_content,但不會報錯,只是效果和match_parent一樣,所以儘量寫明具體高度。
若有問題,請大家多多指正。