美文网首页自定义View
Kevin Learn Android:流程指示器(一)

Kevin Learn Android:流程指示器(一)

作者: Kevin_小飞象 | 来源:发表于2021-07-20 11:36 被阅读0次
    每日一图.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
        }
    }
    

    相关文章

      网友评论

        本文标题:Kevin Learn Android:流程指示器(一)

        本文链接:https://www.haomeiwen.com/subject/pythmltx.html