zoukankan      html  css  js  c++  java
  • android 仿摩拜单车共享单车进度条实现StepView

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6552712.html 

    先看效果图:

     

    Step1:定义StepBean

    定义五个状态,分别为:为完成、正在进行、已完成、终点完成、终点未完成。

    public class StepBean{
        public static final int STEP_UNDO = -1;//未完成
        public static final int STEP_CURRENT = 0;//正在进行
        public static final int STEP_COMPLETED = 1;//已完成
        public static final int STEP_LAST_COMPLETED = 2;//终点完成
        public static final int STEP_LAST_UNCOMPLETED = 3;//终点未完成
        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;
        }
    }

    Step2:自定义HorizontalStepsViewIndicator 

    public class HorizontalStepsViewIndicator extends View {
        private int defaultStepIndicatorNum = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, getResources().getDisplayMetrics());//定义默认的高度
        private float mCompletedLineHeight;//完成线的高度
        private float mCircleRadius;//圆的半径
    
        private Drawable mCompleteIcon;//完成的默认图片
        private Drawable mAttentionIcon;//正在进行的默认图片
        private Drawable mDefaultIcon;//默认的背景图
        private Drawable mLastCompleteIcon;//终点未完成图片
        private Drawable mLastUnCompleteIcon;//终点完成图片
    
        private float mCenterY;//该view的Y轴中间位置
        private float mLeftY;//左上方的Y位置
        private float mRightY;//右下方的位置
    
        private List<StepBean> mStepBeanList ;//当前有几步流程
        private int mStepNum = 0;
        private float mLinePadding;//两条连线之间的间距
    
        private List<Float> mCircleCenterPointPositionList;//定义所有圆的圆心点位置的集合
        private Paint mUnCompletedPaint;//未完成Paint
        private Paint mCompletedPaint;//完成paint
        private int mUnCompletedLineColor = ContextCompat.getColor(getContext(), R.color.uncompleted_color);//定义默认未完成线的颜色
        private int mCompletedLineColor = ContextCompat.getColor(getContext(), R.color.completed_color);//定义默认完成线的颜色
        private PathEffect mEffects;
        private int mComplectingPosition;//正在进行position
    
        private Path mPath;
        private OnDrawIndicatorListener mOnDrawListener;
        private int screenWidth;
    
        /**
         * 设置监听
         * @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();
        }
    
        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);
    
            mCompletedLineHeight = 0.03f * defaultStepIndicatorNum;//已经完成线的宽高
            mCircleRadius = 0.28f * defaultStepIndicatorNum;//圆的半径
            mLinePadding = 1.0f * defaultStepIndicatorNum;//线与线之间的间距
    
            mCompleteIcon = ContextCompat.getDrawable(getContext(), R.drawable.complted);//已经完成的icon
            mAttentionIcon = ContextCompat.getDrawable(getContext(), R.drawable.attention);//正在进行的icon
            mDefaultIcon = ContextCompat.getDrawable(getContext(), R.drawable.default_icon);//未完成的icon
            mLastCompleteIcon= ContextCompat.getDrawable(getContext(), R.drawable.last_complted);//终点已完成的icon
            mLastUnCompleteIcon= ContextCompat.getDrawable(getContext(), R.drawable.last_uncomplted);//终点未完成的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垂直居中
            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);
                }else if(stepsBean.getState()==StepBean.STEP_LAST_COMPLETED){
                    mLastCompleteIcon.setBounds(rect);
                    mLastCompleteIcon.draw(canvas);
                }else if(stepsBean.getState()==StepBean.STEP_LAST_UNCOMPLETED){
                    mLastUnCompleteIcon.setBounds(rect);
                    mLastUnCompleteIcon.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;
        }
    
        public void setLastCompleteIcon(Drawable lastcompleteIcon){
            this.mLastCompleteIcon = lastcompleteIcon;
        }
    
        public void setLastUnCompleteIcon(Drawable lastUnCompleteIcon){
            this.mLastUnCompleteIcon = lastUnCompleteIcon;
        }
    
        /**
         * 设置正在进行中的图片
         * @param attentionIcon
         */
        public void setAttentionIcon(Drawable attentionIcon){
            this.mAttentionIcon = attentionIcon;
        }
    
        /**
         * 设置对view监听
         */
        public interface OnDrawIndicatorListener{
            void ondrawIndicator();
        }
    }

    Step3:自定义HorizontalStepView 

    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(), R.color.completed_color);//定义默认完成文字的颜色;
        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;
        }
    
        public HorizontalStepView setStepsViewIndicatorLastCompleteIcon(Drawable lastCompleteIcon) {
            mStepsViewIndicator.setLastCompleteIcon(lastCompleteIcon);
            return this;
        }
    
        public HorizontalStepView setStepsViewIndicatorLastUnCompleteIcon(Drawable lastUnCompleteIcon) {
            mStepsViewIndicator.setLastUnCompleteIcon(lastUnCompleteIcon);
            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 = 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);
                            mTextView.setTextColor(mComplectedTextColor);
                        } else{
                            mTextView.setTextColor(mUnComplectedTextColor);
                        }
                        mTextContainer.addView(mTextView);
                    }
                }
            }
        }
    }

    Step4:如何使用?

    在布局文件xml中:

    <cn.comnav.utrain.ui.widget.HorizontalStepView
                        android:id="@+id/hsv_step_view"
                        android:layout_width="match_parent"
                        android:layout_height="80dp"
                        android:layout_below="@+id/ll_role"
                        android:layout_marginBottom="40dp"
                        />

    在Activity中的使用,部分代码截取:

    private List<StepBean> stepsBeanList;
                      private HorizontalStepView mHorizontalStepView;
                      mHorizontalStepView=(HorizontalStepView)findViewById(R.id.hsv_step_view);
    
                      stepsBeanList = new ArrayList<>();
                            StepBean stepBean0=null;
                            StepBean stepBean1=null;
                            StepBean stepBean2=null;
                            StepBean stepBean3=null;
                            switch (stepIndex){
                                case 1:
                                    stepBean0 = new StepBean("手机绑定",1);
                                    stepBean1 = new StepBean("实名认证",0);
                                    stepBean2 = new StepBean("学时充值",-1);
                                    stepBean3 = new StepBean("开始用车",3);
                                    break;
                                case 2:
                                    stepBean0 = new StepBean("手机绑定",1);
                                    stepBean1 = new StepBean("实名认证",1);
                                    stepBean2 = new StepBean("学时充值",0);
                                    stepBean3 = new StepBean("开始用车",3);
                                    break;
                                case 3:
                                    stepBean0 = new StepBean("手机绑定",1);
                                    stepBean1 = new StepBean("实名认证",1);
                                    stepBean2 = new StepBean("学时充值",1);
                                    stepBean3 = new StepBean("开始用车",2);
                                    break;
                            }
                            stepsBeanList.add(stepBean0);
                            stepsBeanList.add(stepBean1);
                            stepsBeanList.add(stepBean2);
                            stepsBeanList.add(stepBean3);
                        mHorizontalStepView.setStepViewTexts(stepsBeanList);

    如果此文对您有帮助,微信打赏我一下吧~

  • 相关阅读:
    Linux curl命令详解
    Go语言获取命令行参数
    MySQL对sum()字段 进行条件筛选,使用having,不能用where
    PHP的 first day of 和 last day of
    easyui-datagrid个人实例
    easyui-layout个人实例
    easyui-combotree个人实例
    easyui-combo个人实例
    easyui-combotree个人实例
    easyui datagrid加载数据和分页
  • 原文地址:https://www.cnblogs.com/Joanna-Yan/p/6552712.html
Copyright © 2011-2022 走看看