自定义StepView

来源:互联网 发布:java就业培训课程 编辑:程序博客网 时间:2024/06/13 04:27

背景:

先看写的demo图:

这里写图片描述

项目中有一个需求:就是希望用户进行到哪步,哪步就高亮显示,并且每个步骤的图片都是不同的,完成的和未完成的线条和字也要做相应区分。

我是参考了gtihub上一个开源的stepview(https://github.com/baoyachi/StepView),但是这个不完全符合我的项目需求,所以在其源码上,进行修改和相应调整,然后做出符合自己项目需求的stepview。

具体demo可以从这里下载

代码:

(1)自定义StepView :(只画圆圈和线条)

public class StepView extends View {    //默认线条宽度:    private int defaultStepIndicatorNum = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, getResources().getDisplayMetrics());    private List<Float> mCircleCenterPointPositionList;//定义所有圆的圆心点位置的集合    private Paint mUnCompletedPaint;//未完成Paint    private Paint mCompletedPaint;//完成paint    private int mUnCompletedLineColor = ContextCompat.getColor(getContext(), R.color.uncompleted);//定义默认未完成线的颜色  definition    private float mLinePadding;//两条连线之间的间距    private int mCompletedLineColor = ContextCompat.getColor(getContext(), R.color.completed);//定义默认完成线的颜色    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 int mStepNum = 4;//默认有4个图标,设计4张图片    private Drawable[] defaults = new Drawable[mStepNum];    private ArrayList<Drawable> drawableLists = new ArrayList<>();    private int screenWidth;    private OnDrawIndicatorListener mOnDrawListener;    private int mComplectingPosition;    private float mCompletedLineHeight;//完成线的高度     definition completed line height    private float mCircleRadius;//圆的半径    private String[] mStrList;    private static final int SPACE=20;//为了调整横线的长度    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);        init();    }    private void init() {        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);        mCompletedPaint.setStyle(Paint.Style.FILL);        mUnCompletedPaint.setStyle(Paint.Style.FILL);        //已经完成线的宽高 set mCompletedLineHeight        mCompletedLineHeight = 0.05f * defaultStepIndicatorNum;        //圆的半径  set mCircleRadius        mCircleRadius = 0.28f * defaultStepIndicatorNum;        //线与线之间的间距    set mLinePadding        mLinePadding = 0.85f * defaultStepIndicatorNum+SPACE*4;        //默认有4张图        for(int i=0;i<defaults.length;i++){            defaults[i] = ContextCompat.getDrawable(getContext(), R.drawable.progress01_current);        }    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        //获取中间的高度,目的是为了让该view绘制的线和圆在该view垂直居中          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);        }        if(mOnDrawListener!=null)        {            mOnDrawListener.ondrawIndicator();        }    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, 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 onDraw(Canvas canvas) {        super.onDraw(canvas);        if(mOnDrawListener!=null)        {            mOnDrawListener.ondrawIndicator();        }        mUnCompletedPaint.setColor(mUnCompletedLineColor);        mCompletedPaint.setColor(mCompletedLineColor);        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)//判断在完成之前的所有点            {                //Log.e("hxy","mComplectingPosition="+mComplectingPosition);                //判断在完成之前的所有点,画完成的线,这里是矩形,很细的矩形,类似线                canvas.drawRect(preComplectedXPosition + mCircleRadius - 10, mLeftY, afterComplectedXPosition - mCircleRadius + 10, mRightY, mCompletedPaint);            } else            {                canvas.drawRect(preComplectedXPosition + mCircleRadius,                        mLeftY,                        afterComplectedXPosition - mCircleRadius,                        mRightY, mUnCompletedPaint);            }        }        //图标画小点:        for(int i = 0; i < mCircleCenterPointPositionList.size(); i++)        {            // Log.e("hxy",mCircleCenterPointPositionList.size()+"");            final float currentComplectedXPosition = mCircleCenterPointPositionList.get(i);            Rect rect = new Rect((int) (currentComplectedXPosition - mCircleRadius-10), (int) (mCenterY - mCircleRadius-10), (int) (currentComplectedXPosition + mCircleRadius+10), (int) (mCenterY + mCircleRadius+10));            defaults[i].setBounds(rect);            defaults[i].draw(canvas);        }    }    public void setOnDrawListener(OnDrawIndicatorListener onDrawListener)    {        mOnDrawListener = onDrawListener;    }    public interface OnDrawIndicatorListener    {        void ondrawIndicator();    }    public void setStepNum(String[] stepsBeanList,int position)    {        this.mStrList = stepsBeanList;        mStepNum = stepsBeanList.length;        mComplectingPosition = position;        requestLayout();    }    /**     * 设置已完成线的颜色     *     * @param completedLineColor     */    public void setCompletedLineColor(int completedLineColor)    {        this.mCompletedLineColor = completedLineColor;    }    /**     * 设置默认图片     *     * @param defaultIcons     */    public void setDefaultIcon(Drawable[] defaultIcons)    {        this.defaults = defaultIcons;    }    /**     * 设置未完成线的颜色     *     * @param unCompletedLineColor     */    public void setUnCompletedLineColor(int unCompletedLineColor)    {        this.mUnCompletedLineColor = unCompletedLineColor;    }    /**     * 得到所有圆点所在的位置     *     * @return     */    public List<Float> getCircleCenterPointPositionList()    {        return mCircleCenterPointPositionList;    }}

(2)根据StepView,画出文本:

public class StepViewLayout extends LinearLayout implements StepView.OnDrawIndicatorListener {    private StepView mStepsViewIndicator;    private RelativeLayout mTextContainer;    private String[] mStepBeanList;    private int mUnComplectedTextColor = ContextCompat.getColor(getContext(), R.color.uncompleted);//定义默认未完成文字的颜色;    private int mComplectedTextColor = ContextCompat.getColor(getContext(), R.color.completed);//定义默认完成文字的颜色;    private int mTextSize = 13;//default textSize    private TextView mTextView;    private int mComplectingPosition;    public StepViewLayout(Context context) {        this(context, null);    }    public StepViewLayout(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public StepViewLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    private void init() {        View rootView = LayoutInflater.from(getContext()).inflate(R.layout.widget_stepsview, this);        mStepsViewIndicator = (StepView) rootView.findViewById(R.id.steps_indicator);        mTextContainer = (RelativeLayout) rootView.findViewById(R.id.rl_text_container);        mStepsViewIndicator.setOnDrawListener(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.length; i++)                {                    mTextView = new TextView(getContext());                    mTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSize);                    mTextView.setText(mStepBeanList[i]);                    int spec = MeasureSpec.makeMeasureSpec(0, 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.NORMAL);                        mTextView.setTextColor(mComplectedTextColor);                    } else                    {                        mTextView.setTextColor(mUnComplectedTextColor);                    }                    mTextContainer.addView(mTextView);                }            }        }    }    /**     *     * @param stepsBeanList:文字     * @param position:线条完成的位置,取值从-1算起     * @return     */    public StepViewLayout setStepViewTexts(String[] stepsBeanList,int position)    {        mStepBeanList = stepsBeanList;        mStepsViewIndicator.setStepNum(stepsBeanList,position);        return this;    }    /**     * 设置未完成文字的颜色     *     * @param unComplectedTextColor     * @return     */    public StepViewLayout setStepViewUnComplectedTextColor(int unComplectedTextColor)    {        mUnComplectedTextColor = unComplectedTextColor;        return this;    }    /**     * 设置完成文字的颜色     *     * @param complectedTextColor     * @return     */    public StepViewLayout setStepViewComplectedTextColor(int complectedTextColor)    {        this.mComplectedTextColor = complectedTextColor;        return this;    }    /**     * 设置StepsViewIndicator未完成线的颜色     *     * @param unCompletedLineColor     * @return     */    public StepViewLayout setStepsViewIndicatorUnCompletedLineColor(int unCompletedLineColor)    {        mStepsViewIndicator.setUnCompletedLineColor(unCompletedLineColor);        return this;    }    /**     * 设置StepsViewIndicator完成线的颜色     *     * @param completedLineColor     * @return     */    public StepViewLayout setStepsViewIndicatorCompletedLineColor(int completedLineColor)    {        mStepsViewIndicator.setCompletedLineColor(completedLineColor);        return this;    }    /**     * 设置StepsViewIndicator默认图片     *     * @param defaultIcons     */    public StepViewLayout setStepsViewIndicatorDefaultIcon(Drawable[] defaultIcons)    {        mStepsViewIndicator.setDefaultIcon(defaultIcons);        return this;    }    /**     * set textSize     *     * @param textSize     * @return     */    public StepViewLayout setTextSize(int textSize)    {        if(textSize > 0)        {            mTextSize = textSize;        }        return this;    }    /**     *     * @param Position:圆圈的完成位置:从0开始取     */    public void setComplectingPosition(int Position){        this.mComplectingPosition = Position;    }}其中widget_stepsview的布局如下:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <huang.com.processapp.StepView        android:id="@+id/steps_indicator"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="4dp"        >    </huang.com.processapp.StepView>    <RelativeLayout        android:id="@+id/rl_text_container"        android:layout_width="match_parent"        android:layout_height="wrap_content"        /></LinearLayout>

(3)使用:

//布局:<?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"    android:orientation="vertical"    tools:context="huang.com.processapp.MainActivity">   <huang.com.processapp.StepViewLayout       android:id="@+id/step_view0"       android:layout_width="match_parent"       android:layout_height="wrap_content"       android:layout_marginBottom="20dp"       >   </huang.com.processapp.StepViewLayout>   <huang.com.processapp.StepViewLayout       android:id="@+id/step_view1"       android:layout_width="match_parent"       android:layout_height="wrap_content"       android:layout_marginBottom="20dp"       >   </huang.com.processapp.StepViewLayout>   <huang.com.processapp.StepViewLayout       android:id="@+id/step_view2"       android:layout_width="match_parent"       android:layout_height="wrap_content"       android:layout_marginBottom="20dp"       >   </huang.com.processapp.StepViewLayout>   <huang.com.processapp.StepViewLayout       android:id="@+id/step_view3"       android:layout_width="match_parent"       android:layout_height="wrap_content"       android:layout_marginBottom="20dp"       >   </huang.com.processapp.StepViewLayout></LinearLayout>//代码:{        StepViewLayout setpview = (StepViewLayout) findViewById(R.id.step_view0);        setpview.setComplectingPosition(0);        String[] all = {"1.选择日期","2.支付","3.扫码开锁","4.使用工作室"};        Drawable[] defaultIcons = new Drawable[4];        defaultIcons[0] = ContextCompat.getDrawable(this, R.drawable.progress01_current);        defaultIcons[1] = ContextCompat.getDrawable(this, R.drawable.progress02);        defaultIcons[2] = ContextCompat.getDrawable(this, R.drawable.progress03);        defaultIcons[3] = ContextCompat.getDrawable(this, R.drawable.progress04);        setpview.setStepViewTexts(all,-1)//completeposition 是线条的位置:                .setTextSize(14)//set textSize                .setStepsViewIndicatorCompletedLineColor(ContextCompat.getColor(this, R.color.completed))//设置StepsViewIndicator完成线的颜色                .setStepsViewIndicatorUnCompletedLineColor(ContextCompat.getColor(this, R.color.uncompleted))//设置StepsViewIndicator未完成线的颜色                .setStepViewComplectedTextColor(ContextCompat.getColor(this, R.color.completed))//设置StepsView text完成线的颜色                .setStepViewUnComplectedTextColor(ContextCompat.getColor(this, R.color.uncompleted))//设置StepsView text未完成线的颜色                .setStepsViewIndicatorDefaultIcon(defaultIcons);//设置StepsViewIndicator DefaultIcon}