自定义步骤View--StepView

来源:互联网 发布:energia驱动mac 编辑:程序博客网 时间:2024/05/22 00:42

最近遇到一个按步骤走流程的需求,相信其他的程序员也会遇到这样的需求吧,好了下面说一下我解决这个问题的过程


刚接到这个需求的时候,我是使用布局的方式画的,很长很乱,适配是发现,那是相当的烂啊,根本无法满足适配的需要,无语啊。代码就不贴了哈。


还是转换思路,自己写吧,于是就简单的写一个。代码如下:

思路如下:

   先写出7个方法,每个方法实现的是每个步骤的状态,画出圆点、连线、每个步骤的名称

import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;public class StepView extends View {    private int mWidth;//view的总宽度    private Bitmap curImage;//当前步骤图片    private Bitmap passedImage;//已完成步骤图片    private Bitmap unPassImage;//未完成步骤图片    private Paint paint;//bitmap使用的画笔    private Paint linePaint;//画线使用的画笔    private float lineWidth;//步骤之间每根线的长度    private int lineCount = 6;//共多少条连线    /**     * 当前图片与未完成和完成图片大小不一致     * 且图片要在一条直线上,因此,画完成和未完成     * 的图片时要计算出marginTop     */    private float unpassTop = 0;    private Paint textPait;//画文字时需要的画笔    private int curIndex = 0;//当前步骤    private int marginTop = 40;//文字与图片之间的间距    public StepView(Context context) {        super(context);        init();    }    public StepView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    public StepView(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    private void init(){        //初始化图片        curImage = BitmapFactory.decodeResource(getResources(), R.drawable.process_current);        passedImage = BitmapFactory.decodeResource(getResources(), R.drawable.process_passed);        unPassImage = BitmapFactory.decodeResource(getResources(), R.drawable.process_unpass);        //初始化画笔        paint = new Paint();        linePaint = new Paint();        linePaint.setAntiAlias(true);        linePaint.setStrokeWidth(5);        linePaint.setColor(Color.parseColor("#cfcfcf"));        textPait = new Paint();        textPait.setAntiAlias(true);        textPait.setTextSize(36);        textPait.setColor(Color.parseColor("#eeaa2f"));    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        //设置宽度,随着view的宽度的变化而变化        this.mWidth = w;        //计算步骤之间线条的长度        lineWidth = (float)(mWidth - passedImage.getWidth() * lineCount - curImage.getWidth()) / lineCount;        //计算完成与未完成图片与View顶部的间距        unpassTop = (curImage.getHeight() - unPassImage.getHeight()) / 2;    }    
@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        float startX = 0;        for(int i = 0; i<= lineCount; i++){            //先画点,当前步骤之前为已完成,当前步骤之后为未完成            if(curIndex > i){                drawCircleBitmap(canvas,startX,passedImage,unpassTop);            }else if(curIndex == i){                drawCircleBitmap(canvas,startX,curImage,0);            }else{                drawCircleBitmap(canvas,startX,unPassImage,unpassTop);            }            //画文字            drawText(i,canvas,startX,curIndex);            //画线条            if(curIndex > i){                //计算新的起始位置                startX += passedImage.getWidth();                drawLine(canvas,startX,Color.parseColor("#eeaa2f"));            }else if(curIndex == i){                if(i != 6){                    //计算新的起始位置                    startX += curImage.getWidth();                    drawLine(canvas,startX,Color.parseColor("#cfcfcf"));                }            }else{                if(i != 6){                    //计算新的起始位置                    startX += unPassImage.getWidth();                    drawLine(canvas,startX,Color.parseColor("#cfcfcf"));                }            }            //计算新的起始位置            startX += lineWidth;        }    }    private void drawCircleBitmap(Canvas canvas,float startX,Bitmap bitmap,float marginTop){        canvas.drawBitmap(bitmap,startX,marginTop,paint);    }    private void drawLine(Canvas canvas,float startX,int color){        linePaint.setColor(color);        canvas.drawLine(startX,curImage.getHeight() / 2,startX + lineWidth,curImage.getHeight() / 2,linePaint);    }    private void drawText(int index,Canvas canvas,float startX,int curIndex){        if(index <= curIndex){            textPait.setColor(Color.parseColor("#eeaa2f"));        }else{            textPait.setColor(Color.parseColor("#cfcfcf"));        }        if(index == 0){            canvas.drawText("第一步",0,curImage.getHeight() + marginTop,textPait);        }else if(index == 1){            if(curIndex == 1){                canvas.drawText("第二步",startX - 25,curImage.getHeight() + marginTop,textPait);            }else{                canvas.drawText("第二步",startX - 35,curImage.getHeight() + marginTop,textPait);            }        }else if(index == 2){            if(curIndex == 2){                canvas.drawText("第三步",startX - 25,curImage.getHeight() + marginTop,textPait);            }else{                canvas.drawText("第三步",startX - 35,curImage.getHeight() + marginTop,textPait);            }        }else if(index == 3){            if(curIndex == 3){                canvas.drawText("第四步",startX - 25,curImage.getHeight() + marginTop,textPait);            }else{                canvas.drawText("第四步",startX - 35,curImage.getHeight() + marginTop,textPait);            }        }else if(index == 4){            if(curIndex == 4){                canvas.drawText("第五步",startX - 25,curImage.getHeight() + marginTop,textPait);            }else{                canvas.drawText("第五步",startX - 35,curImage.getHeight() + marginTop,textPait);            }        }else if(index == 5){            if(curIndex == 5){                canvas.drawText("第六步",startX - 25,curImage.getHeight() + marginTop,textPait);            }else{                canvas.drawText("第六步",startX - 35,curImage.getHeight() + marginTop,textPait);            }        }else if(index == 6){            canvas.drawText("第七步",mWidth - 90,curImage.getHeight() + marginTop,textPait);        }    }
    public void setCurIndex(int curIndex) {        this.curIndex = curIndex;        invalidate();    }}
以上的代码是有缺陷,当文字大小改变后,产生的问题需要重新计算,这对适配来说是非常痛苦的,在使用过程中发现了这个问题,故对比做了进一步的优化。
public class StepView extends View {    private int mWidth;//view的总宽度    private Bitmap curImage;//当前步骤图片    private Bitmap passedImage;//已完成步骤图片    private Bitmap unPassImage;//未完成步骤图片    private Paint paint;//bitmap使用的画笔    private Paint linePaint;//画线使用的画笔    private float lineWidth;//步骤之间每根线的长度    private int lineCount = 0;//共多少条连线    /**     * 当前图片与未完成和完成图片大小不一致     * 且图片要在一条直线上,因此,画完成和未完成     * 的图片时要计算出marginTop     */    private float unpassTop = 0;    private Paint textPait;//画文字时需要的画笔    private int curIndex = 0;//当前步骤    private int marginTop = 15;//文字与图片之间的间距    private int textSize = 12;//文字大小    private int passedImageWidth;    private int curImageWidth;    private int unpassImageWidth;    private int startTextY;    private String[] texts = {"第一步", "第二步", "第三步", "第四步", "第五步", "第六步", "第七步"};    private float[] textLengths = new float[7];    public StepView(Context context) {        super(context);        init(context);    }    public StepView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    public StepView(Context context, AttributeSet attrs) {        super(context, attrs);        init(context);    }    private void init(Context context) {        //初始化图片        curImage = BitmapFactory.decodeResource(getResources(), R.drawable.process_current);        passedImage = BitmapFactory.decodeResource(getResources(), R.drawable.process_passed);        unPassImage = BitmapFactory.decodeResource(getResources(), R.drawable.process_unpass);        textSize = dip2px(context, textSize);        marginTop = dip2px(context, marginTop);        lineCount = texts.length - 1;        passedImageWidth = passedImage.getWidth();        curImageWidth = curImage.getWidth();        unpassImageWidth = unPassImage.getWidth();        startTextY = curImage.getHeight() + marginTop;        //初始化画笔        paint = new Paint();        linePaint = new Paint();        linePaint.setAntiAlias(true);        linePaint.setStrokeWidth(5);        linePaint.setColor(Color.parseColor("#cfcfcf"));        textPait = new Paint();        textPait.setAntiAlias(true);        textPait.setTextSize(textSize);        textPait.setColor(Color.parseColor("#eeaa2f"));        for (int i = 0, len = texts.length; i < len; i++) {            textLengths[i] = getTextLength(texts[i]);        }    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        //设置宽度,随着view的宽度的变化而变化        this.mWidth = w;        //计算步骤之间线条的长度        lineWidth = (float) (mWidth - passedImageWidth * lineCount - curImageWidth) / lineCount;        //计算完成与未完成图片与View顶部的间距        unpassTop = (curImage.getHeight() - unPassImage.getHeight()) / 2;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        float startX = 0;        for (int i = 0; i <= lineCount; i++) {            //先画点,当前步骤之前为已完成,当前步骤之后为未完成            if (curIndex > i) {                drawCircleBitmap(canvas, startX, passedImage, unpassTop);            } else if (curIndex == i) {                drawCircleBitmap(canvas, startX, curImage, 0);            } else {                drawCircleBitmap(canvas, startX, unPassImage, unpassTop);            }            //画文字            drawText(i, canvas, startX, curIndex, curIndex == i);            //画线条            if (curIndex > i) {                //计算新的起始位置                startX += passedImageWidth;                drawLine(canvas, startX, Color.parseColor("#eeaa2f"));            } else if (curIndex == i) {                if (i != 6) {                    //计算新的起始位置                    startX += curImageWidth;                    drawLine(canvas, startX, Color.parseColor("#cfcfcf"));                }            } else {                if (i != 6) {                    //计算新的起始位置                    startX += unpassImageWidth;                    drawLine(canvas, startX, Color.parseColor("#cfcfcf"));                }            }            //计算新的起始位置            startX += lineWidth;        }    }    private void drawCircleBitmap(Canvas canvas, float startX, Bitmap bitmap, float marginTop) {        canvas.drawBitmap(bitmap, startX, marginTop, paint);    }    private void drawLine(Canvas canvas, float startX, int color) {        linePaint.setColor(color);        canvas.drawLine(startX, curImage.getHeight() / 2, startX + lineWidth, curImage.getHeight() / 2, linePaint);    }    private void drawText(int index, Canvas canvas, float startX, int curIndex, boolean isCur) {        int div = isCur ? curImageWidth / 2 : passedImageWidth / 2;        if (index <= curIndex) {            textPait.setColor(Color.parseColor("#eeaa2f"));        } else {            textPait.setColor(Color.parseColor("#cfcfcf"));        }        if (index == 0) {            canvas.drawText(texts[0], 0, startTextY, textPait);        } else if (index == texts.length - 1) {            canvas.drawText(texts[texts.length - 1], mWidth - textLengths[index], startTextY, textPait);        } else {            canvas.drawText(texts[index], startX + div - textLengths[index] / 2, startTextY, textPait);        }    }    public void setCurIndex(int curIndex) {        this.curIndex = curIndex;        invalidate();    }    private float getTextLength(String text) {        // 使用panit获取文字的宽度        float textLength = textPait.measureText(text);        return textLength;    }    /**     * dip 2 px     *     * @param context     * @param dipValue     * @return 上午11:37:12     */    private int dip2px(Context context, int dipValue) {        final float scale = context.getResources().getDisplayMetrics().density;        return (int) (dipValue * scale);    }}
以上就是全部的代码实现,初步的封装了步骤的变化,其实还可以进一步封装,比如自定义属性,步骤总数、步骤标题集合,已完成步骤的颜色、当前步骤颜色、未完成步骤颜色等等,希望有兴趣的同学进行进一步的封装
需要的图片资源已经上传,本想着把第一步即每个步骤为一个方法实现的代码贴出来的,实在是太麻烦啦,就算啦。
欢迎各位指正!

0 0
原创粉丝点击