在做项目的过程中原型图里画了一个这样的UI,请看下图:
实现这个UI其实也不难,直接在XML布局里面也可以实现,就是麻烦一点。但是根据我们公司的产品经理的设计思路,肯定不能画死的,所以我想还是用代码画出来,不限制只有三个节点流程(目前只有三个节点流程)。
有了需求咱们就该想思路,我的思路是获取当前view的宽度,对比当前的宽度分为八个圆点(如果你想圆点与圆点之间的间隔短一点那就多分几个),然后计算文字的宽度相对于圆点的剧中位置,得到位置之后就改画了。在画完第一个之后进入for循环继续画出第二个点。逻辑有点不清楚还是直接看代码吧!
public class LineView extends View {
private int mRoundLeft = 50;
private int mRoundRight = 70;
private int mRoundTop = 130;
private int mRoundBottom = 170;
private int mRoundSize = 20;//圆的直径
private Paint mPaint;
private TextPaint tp;
private int mAlphaRoundSize = 30;//透明圆直径
private int tag;
private String[] text_name = {"发起","审批中","完成"};
public LineView(Context context) {
super(context);
}
public LineView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
onRund(canvas);
}
public void setData(int tag){
this.tag = tag;
}
private void onRund(Canvas canvas) {
//获取控件宽度、高度
int height = getHeight();
int width = getWidth();
int win_heightcenter = height / 4;//view的高度的四分之一
int mRoundHeight = height - win_heightcenter;//圆距离顶部的位置
int mRroundSize = mRoundSize / 2;//圆的半径
mRoundTop = mRoundHeight-mRroundSize;//圆的顶部位置
mRoundBottom = mRoundHeight+mRroundSize;//圆的底部位置
int width_item = width / 8;//宽度分成八个流程节点每个流程节点对应的宽度
mRoundLeft = width_item - mRroundSize;//圆点左边对应对左边的边距
mRoundRight = width_item + mRroundSize;//圆点右边对应左边的边距
mPaint = new Paint();
Paint mLinePaint = new Paint();
// canvas.drawRect(110,10,210,110,mPaint);
// 定义一个矩形
// 画圆
int mLineTopBootom = mRoundTop + (mRoundBottom - mRoundTop)/2;
tp = new TextPaint();
for (int a = 0;a<3;a++){
// 设置文字大小
tp.setTextSize(height/3);
//文字字体加粗
tp.setFakeBoldText(true);
mLinePaint.setStrokeWidth(5);//笔宽5像素
if(tag==0){
if(a==0||a==1){
mPaint.setColor(Color.parseColor("#056eb4"));
tp.setColor(Color.parseColor("#056eb4"));
}else{
mPaint.setColor(Color.parseColor("#c1c1c1"));
tp.setColor(Color.parseColor("#c1c1c1"));
}
if(a==0){
mLinePaint.setColor(Color.parseColor("#056eb4"));
}else{
mLinePaint.setColor(Color.parseColor("#c1c1c1"));
}
}else{
mLinePaint.setColor(Color.parseColor("#c1c1c1"));
tp.setColor(Color.parseColor("#c1c1c1"));
mPaint.setColor(Color.parseColor("#c1c1c1"));
}
// 计算文字的宽度
int textWidth = getTextWidth(tp, text_name[a]);
Log.i("TAG", "文字宽度: "+textWidth);
// 画圆
RectF rf2 = new RectF(mRoundLeft, mRoundTop, mRoundRight, mRoundBottom);
canvas.drawOval(rf2, mPaint);
// 计算圆的中心点得到文字X轴的位置
int i = mRoundRight - (mRoundRight - mRoundLeft) /2 ;//圆的中心点
int t = i - textWidth / 2;//文字X位置
// 绘制文字
canvas.drawText(text_name[a],t,mRoundHeight - mRoundSize , tp);
if(a != 2) {
// 绘制线
canvas.drawLine(mRoundRight, mLineTopBootom, mRoundRight + 200, mLineTopBootom, mLinePaint);
}
// 透明圆
if(tag==0){
if(a==1){
mPaint.setAlpha(100);
RectF rf3 = new RectF(mRoundLeft-5, mRoundTop-5, mRoundRight+5, mRoundBottom+5);
canvas.drawOval(rf3, mPaint);
}
}else{
if(a==2){
mPaint.setAlpha(100);
RectF rf3 = new RectF(mRoundLeft-5, mRoundTop-5, mRoundRight+5, mRoundBottom+5);
canvas.drawOval(rf3, mPaint);
}
}
// 下一个节点的位置
mRoundRight = mRoundRight + 200;
mRoundLeft = mRoundLeft + 200;
mPaint.reset();
tp.reset();
// tp.setColor(Color.RED);
// mPaint.setColor(Color.GRAY);
}
}
// 计算文字宽度
public static int getTextWidth(Paint paint, String str) {
int iRet = 0;
if (str != null && str.length() > 0) {
int len = str.length();
float[] widths = new float[len];
paint.getTextWidths(str, widths);
for (int j = 0; j < len; j++) {
iRet += (int) Math.ceil(widths[j]);
}
}
return iRet;
}
}
代码里我写了一个公共方法setData(int tag),传入0和1,是用来控制当前显示第几个节点的。因为当前项目里面只用到三个节点,我就把三个节点的名字写死了,放在数组里面,当然你们也可以写一个公共的方法,set进去。
在使用的时候直接在代码里使用当前View就行了,但是不要忘了要实现setData方法。