首页 > 移动平台 > 详细

Android订单流程view(超简单!)

时间:2017-03-28 14:16:50      阅读:308      评论:0      收藏:0      [点我收藏+]

前言:最近在做rn、h5然后时不时的再来一点android的需求,尼玛~~感觉不要不要的啊,思维都混淆了都,不管咋样,多学点技术还是不错的,所以还是加油吧!

在群里看到小伙伴发了这么一个需求,先看看最终效果图:

技术分享

怎么样,效果还是很不错的吧?群里有人说切四张图的、recycleview的、各种的都有啊,但是最简单的就是通过自定义view来实现了~接下来让我们来实现下这个(订单流程view)。

首先我们定义好我们的自定义属性:

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ProcessView">
        <!--滑动圆点的半径-->
        <attr name="thumb_radius" format="dimension"/>
        <!--到达的颜色-->
        <attr name="color_reached" format="color"/>
        <!--未到达的颜色-->
        <attr name="color_unreached" format="color"/>
        <!--textsize的大小-->
        <attr name="textsize" format="dimension"/>
        <!--text的颜色-->
        <attr name="text_color" format="color"/>
        <!--线的宽度-->
        <attr name="line_width" format="dimension"/>
        <!--状态文字数组-->
        <attr name="texts" format="reference"/>
    </declare-styleable>
</resources>

然后就是我们的老套路了,创建一个叫ProcessView的类继承view,然后定义好我们需要的属性:

/**
 * Created by leo on 17/3/27.
 */

public class ProcessView extends View {
    /**
     * 默认线宽度
     */
    private static final float D_LINE_WIDTH = 3;
    /**
     * 默认滑动圆点半径
     */
    private static final float D_THUMB_RADIUS = 10;
    /**
     * 默认textsize
     */
    private static final float D_TEXT_SIZE = 13f;
    private static final int D_REACH_COLOR = 0xFFF1AE0D;
    private static final int D_UNREACH_COLOR = Color.WHITE;
    private static final int D_TEXT_COLOR = Color.WHITE;

    private Paint linePaint;
    private TextPaint textPaint;
    private Paint thumbPaint;

    private float mTextSize = xx2px(TypedValue.COMPLEX_UNIT_SP, D_TEXT_SIZE);
    private float mLineWidth = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_LINE_WIDTH);
    private float mThumbRadius = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_THUMB_RADIUS);
    private int mReachedColor = D_REACH_COLOR;
    private int mUnreachedColor = D_UNREACH_COLOR;
    private int mTextColor = D_TEXT_COLOR;

    //当前进度
    private float mProgress = 0.0f;
    //所有的状态文字
    private String[] texts;

    public ProcessView(Context context) {
        this(context, null);
    }

    public ProcessView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ProcessView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainStyledAttrs(context, attrs, defStyleAttr);
        initViews();
    }

    /**
     * 获取我们的自定义属性
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProcessView, defStyleAttr, 0);
        texts = a.hasValue(R.styleable.ProcessView_texts) ?
                getResources().getStringArray(a.getResourceId(R.styleable.ProcessView_texts, 0)) : texts;
        mLineWidth = a.hasValue(R.styleable.ProcessView_line_width) ?
                a.getDimensionPixelSize(R.styleable.ProcessView_line_width, 0) : mLineWidth;
        mThumbRadius = a.hasValue(R.styleable.ProcessView_thumb_radius) ?
                a.getDimensionPixelSize(R.styleable.ProcessView_thumb_radius, 0) : mThumbRadius;
        mTextSize = a.hasValue(R.styleable.ProcessView_textsize) ?
                a.getDimensionPixelSize(R.styleable.ProcessView_text_color, 0) : mTextSize;
        mReachedColor=a.hasValue(R.styleable.ProcessView_color_reached)?
                a.getColor(R.styleable.ProcessView_color_reached,D_REACH_COLOR):D_REACH_COLOR;
        mUnreachedColor=a.hasValue(R.styleable.ProcessView_color_unreached)?
                a.getColor(R.styleable.ProcessView_color_unreached,D_UNREACH_COLOR):D_UNREACH_COLOR;
        mTextColor=a.hasValue(R.styleable.ProcessView_text_color)?
                a.getColor(R.styleable.ProcessView_text_color,D_TEXT_COLOR):D_TEXT_COLOR;
        a.recycle();
    }

    /**
     * 初始化一些对象
     */
    private void initViews() {
        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
        linePaint.setStyle(Paint.Style.FILL);
        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
        thumbPaint = new Paint(linePaint);

        textPaint.setTextSize(mTextSize);
        textPaint.setColor(mTextColor);
        linePaint.setStrokeWidth(mLineWidth);

    }
 }

然后就是重写我们的onmeasure方法了,我们这里就不考虑控件的高度为wrap_content这种情况了,所以我们只需要测量高度就可以了:

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightM = MeasureSpec.getMode(heightMeasureSpec);
        int defaultW = MeasureSpec.getSize(widthMeasureSpec);
        int defaultH = MeasureSpec.getSize(heightMeasureSpec);
        int resultW, resultH;
        resultW = defaultW;
        resultH = getDefaultHeight(defaultH, heightM);
        setMeasuredDimension(resultW, resultH);
    }

    private int getDefaultHeight(int height, int mode) {
        int result;
        if (mode == MeasureSpec.EXACTLY) {
            result = height;
        } else {
            //获取文字的高度
            float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top);
            //高度=圆半径+2.2*线条宽度(也就是竖线高度)+文字高度*1.3(也就是空隙高度)+0.5*文字高度
            result = (int) (mThumbRadius + mLineWidth * 2.2f + textH * 1.3f + 0.5 * textH);
        }
        return result;
    }

接着就是我们的核心方法onDraw()了,代码很简单都有注释,我就不一一解释了:

@Override
    protected void onDraw(Canvas canvas) {
        //画底部的竖线跟文字
        drawFoot(canvas);
        //画移动的小圆点跟进度条
        drawProgressAndThumb(canvas);
    }

    /**
     * 画底部的竖线跟文字
     */
    private void drawFoot(Canvas canvas) {
        //设置底部竖线宽度(底部的竖线会比进度条的要小一点)
        float lineWidth = mLineWidth * 0.8f;
        linePaint.setStrokeWidth(mLineWidth * 0.8f);
        //起始位置(也就是"订单已提交"的"已"字位置)
        float startX = textPaint.measureText(texts[0]) / 2;
        //结束的文字的位置("已送达"的"送"字位置)
        float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2;
        //绘制的终点位置
        float endX = getMeasuredWidth() - endTextW;
        //线条的总长度
        float lineW = (endX - startX) / (texts.length - 1);
        //竖线的高度
        float lineH = mLineWidth * 2.2f;
        //竖线的终点位置
        float lineY = mThumbRadius + mLineWidth / 2;
        //循环画出竖线跟文字
        for (int i = 0; i < texts.length; i++) {
            canvas.save();
            //每画一条竖线让画布水平平移linew个宽度
            canvas.translate(i * lineW, 0);
            //如果当前进度>竖线所在的位置,就改变竖线的颜色
            linePaint.setColor(i * lineW >= mProgress * (endX - startX) ? mUnreachedColor : mReachedColor);
            float endX2 = i == texts.length - 1 ? startX - lineWidth / 2 : startX + lineWidth / 2;
            canvas.drawLine(endX2, lineY, endX2, lineY + lineH, linePaint);

            //画文字
            textPaint.setTextAlign(Paint.Align.CENTER);
            float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top);
            canvas.drawText(texts[i], endX2, lineY + lineH + textH * 1.3f, textPaint);
            canvas.restore();
        }
    }

    private void drawProgressAndThumb(Canvas canvas) {
        float startX = textPaint.measureText(texts[0]) / 2;
        float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2;
        float endX = getMeasuredWidth() - endTextW;
        float lineY = mThumbRadius;
        linePaint.setStrokeWidth(mLineWidth);
        //draw basic line
        linePaint.setColor(mUnreachedColor);
        canvas.drawLine(startX, lineY, endX, lineY, linePaint);
        //draw progress line
        float progressX = startX + (endX - startX) * mProgress;
        linePaint.setColor(mReachedColor);
        canvas.drawLine(startX, lineY, progressX, lineY, linePaint);
        //给移动圆点一个RadialGradient颜色梯度效果
        thumbPaint.setShader(new RadialGradient(progressX, mThumbRadius, mThumbRadius, new int[]{Color.WHITE, D_REACH_COLOR, Color.YELLOW}, null, Shader.TileMode.REPEAT));
        canvas.drawCircle(progressX, mThumbRadius, mThumbRadius, thumbPaint);
    }

好啦~~然后我们暴露一个方法给外部,修改progress:

 public void setProgress(float progress) {
        if (progress != mProgress) {
            mProgress = progress;
            if (Looper.myLooper() == Looper.getMainLooper()) {
                invalidate();
            } else {
                postInvalidate();
            }
        }
    }

最后我们就可以跑起来了:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:background="#b2000000"
    android:orientation="vertical"
    >
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardCornerRadius="5dp"
        app:cardElevation="3dp"
        app:cardBackgroundColor="#FF2384DD"
        >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="10dp"
            >
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="商家已接单"
                android:textSize="14.5sp"
                android:textColor="#FFF1AE0D"
                />
            <TextView
                android:layout_marginTop="5dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="订单超过12小时自动完成"
                android:textSize="13sp"
                android:textColor="#fff"
                />
            <View
                android:layout_marginTop="10dp"
                android:layout_marginBottom="10dp"
                android:layout_width="match_parent"
                android:layout_height="2dp"
                android:background="@drawable/bg_line"
                android:layerType="software"
                />
            <com.yasin.processdemo.view.ProcessView
                android:id="@+id/id_process"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:texts="@array/process_states"
                />
        </LinearLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>

arrays.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="process_states">
        <item>订单已提交</item>
        <item>已付款</item>
        <item>商家已接单</item>
        <item>已送达</item>
    </array>
</resources>

然后是我们的测试activity:

package com.yasin.processdemo;

import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.animation.AccelerateDecelerateInterpolator;

import com.yasin.processdemo.view.ProcessView;

public class MainActivity extends AppCompatActivity {
    private ProcessView mProcessView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mProcessView= (ProcessView) findViewById(R.id.id_process);
        startAni();
    }
    private void startAni() {
        ValueAnimator a = ValueAnimator.ofFloat(0, 1);
        a.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float progress = (float) animation.getAnimatedValue();
                mProcessView.setProgress(progress);
            }
        });
        a.setDuration(10000);
        a.setInterpolator(new AccelerateDecelerateInterpolator());
        a.start();
    }
}

最后附上processview的全部代码:

package com.yasin.processdemo.view;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.os.Looper;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import com.yasin.processdemo.R;


/**
 * Created by leo on 17/3/27.
 */

public class ProcessView extends View {
    /**
     * 默认线宽度
     */
    private static final float D_LINE_WIDTH = 3;
    /**
     * 默认滑动圆点半径
     */
    private static final float D_THUMB_RADIUS = 10;
    /**
     * 默认textsize
     */
    private static final float D_TEXT_SIZE = 13f;
    private static final int D_REACH_COLOR = 0xFFF1AE0D;
    private static final int D_UNREACH_COLOR = Color.WHITE;
    private static final int D_TEXT_COLOR = Color.WHITE;

    private Paint linePaint;
    private TextPaint textPaint;
    private Paint thumbPaint;

    private float mTextSize = xx2px(TypedValue.COMPLEX_UNIT_SP, D_TEXT_SIZE);
    private float mLineWidth = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_LINE_WIDTH);
    private float mThumbRadius = xx2px(TypedValue.COMPLEX_UNIT_DIP, D_THUMB_RADIUS);
    private int mReachedColor = D_REACH_COLOR;
    private int mUnreachedColor = D_UNREACH_COLOR;
    private int mTextColor = D_TEXT_COLOR;

    //当前进度
    private float mProgress = 0.0f;
    //所有的状态文字
    private String[] texts;

    public ProcessView(Context context) {
        this(context, null);
    }

    public ProcessView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ProcessView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        obtainStyledAttrs(context, attrs, defStyleAttr);
        initViews();
    }

    /**
     * 获取我们的自定义属性
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    private void obtainStyledAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProcessView, defStyleAttr, 0);
        texts = a.hasValue(R.styleable.ProcessView_texts) ?
                getResources().getStringArray(a.getResourceId(R.styleable.ProcessView_texts, 0)) : texts;
        mLineWidth = a.hasValue(R.styleable.ProcessView_line_width) ?
                a.getDimensionPixelSize(R.styleable.ProcessView_line_width, 0) : mLineWidth;
        mThumbRadius = a.hasValue(R.styleable.ProcessView_thumb_radius) ?
                a.getDimensionPixelSize(R.styleable.ProcessView_thumb_radius, 0) : mThumbRadius;
        mTextSize = a.hasValue(R.styleable.ProcessView_textsize) ?
                a.getDimensionPixelSize(R.styleable.ProcessView_text_color, 0) : mTextSize;
        mReachedColor=a.hasValue(R.styleable.ProcessView_color_reached)?
                a.getColor(R.styleable.ProcessView_color_reached,D_REACH_COLOR):D_REACH_COLOR;
        mUnreachedColor=a.hasValue(R.styleable.ProcessView_color_unreached)?
                a.getColor(R.styleable.ProcessView_color_unreached,D_UNREACH_COLOR):D_UNREACH_COLOR;
        mTextColor=a.hasValue(R.styleable.ProcessView_text_color)?
                a.getColor(R.styleable.ProcessView_text_color,D_TEXT_COLOR):D_TEXT_COLOR;
        a.recycle();
    }

    /**
     * 初始化一些对象
     */
    private void initViews() {
        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
        linePaint.setStyle(Paint.Style.FILL);
        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
        thumbPaint = new Paint(linePaint);

        textPaint.setTextSize(mTextSize);
        textPaint.setColor(mTextColor);
        linePaint.setStrokeWidth(mLineWidth);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightM = MeasureSpec.getMode(heightMeasureSpec);
        int defaultW = MeasureSpec.getSize(widthMeasureSpec);
        int defaultH = MeasureSpec.getSize(heightMeasureSpec);
        int resultW, resultH;
        resultW = defaultW;
        resultH = getDefaultHeight(defaultH, heightM);
        setMeasuredDimension(resultW, resultH);
    }

    private int getDefaultHeight(int height, int mode) {
        int result;
        if (mode == MeasureSpec.EXACTLY) {
            result = height;
        } else {
            //获取文字的高度
            float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top);
            //高度=圆半径+2.2*线条宽度(也就是竖线高度)+文字高度*1.3(也就是空隙高度)+0.5*文字高度
            result = (int) (mThumbRadius + mLineWidth * 2.2f + textH * 1.3f + 0.5 * textH);
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //画底部的竖线跟文字
        drawFoot(canvas);
        //画移动的小圆点跟进度条
        drawProgressAndThumb(canvas);
    }

    /**
     * 画底部的竖线跟文字
     */
    private void drawFoot(Canvas canvas) {
        //设置底部竖线宽度(底部的竖线会比进度条的要小一点)
        float lineWidth = mLineWidth * 0.8f;
        linePaint.setStrokeWidth(mLineWidth * 0.8f);
        //起始位置(也就是"订单已提交"的"已"字位置)
        float startX = textPaint.measureText(texts[0]) / 2;
        //结束的文字的位置("已送达"的"送"字位置)
        float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2;
        //绘制的终点位置
        float endX = getMeasuredWidth() - endTextW;
        //线条的总长度
        float lineW = (endX - startX) / (texts.length - 1);
        //竖线的高度
        float lineH = mLineWidth * 2.2f;
        //竖线的终点位置
        float lineY = mThumbRadius + mLineWidth / 2;
        //循环画出竖线跟文字
        for (int i = 0; i < texts.length; i++) {
            canvas.save();
            //每画一条竖线让画布水平平移linew个宽度
            canvas.translate(i * lineW, 0);
            //如果当前进度>竖线所在的位置,就改变竖线的颜色
            linePaint.setColor(i * lineW >= mProgress * (endX - startX) ? mUnreachedColor : mReachedColor);
            float endX2 = i == texts.length - 1 ? startX - lineWidth / 2 : startX + lineWidth / 2;
            canvas.drawLine(endX2, lineY, endX2, lineY + lineH, linePaint);

            //画文字
            textPaint.setTextAlign(Paint.Align.CENTER);
            float textH = (textPaint.getFontMetrics().bottom - textPaint.getFontMetrics().top);
            canvas.drawText(texts[i], endX2, lineY + lineH + textH * 1.3f, textPaint);
            canvas.restore();
        }
    }

    private void drawProgressAndThumb(Canvas canvas) {
        float startX = textPaint.measureText(texts[0]) / 2;
        float endTextW = textPaint.measureText(texts[texts.length - 1]) / 2;
        float endX = getMeasuredWidth() - endTextW;
        float lineY = mThumbRadius;
        linePaint.setStrokeWidth(mLineWidth);
        //draw basic line
        linePaint.setColor(mUnreachedColor);
        canvas.drawLine(startX, lineY, endX, lineY, linePaint);
        //draw progress line
        float progressX = startX + (endX - startX) * mProgress;
        linePaint.setColor(mReachedColor);
        canvas.drawLine(startX, lineY, progressX, lineY, linePaint);
        //给移动圆点一个RadialGradient颜色梯度效果
        thumbPaint.setShader(new RadialGradient(progressX, mThumbRadius, mThumbRadius, new int[]{Color.WHITE, D_REACH_COLOR, Color.YELLOW}, null, Shader.TileMode.REPEAT));
        canvas.drawCircle(progressX, mThumbRadius, mThumbRadius, thumbPaint);
    }

    public void setProgress(float progress) {
        if (progress != mProgress) {
            mProgress = progress;
            if (Looper.myLooper() == Looper.getMainLooper()) {
                invalidate();
            } else {
                postInvalidate();
            }
        }
    }

    private float xx2px(int unit, float value) {
        Context c = getContext();
        Resources r;
        if (c == null)
            r = Resources.getSystem();
        else
            r = c.getResources();
        return (TypedValue.applyDimension(
                unit, value, r.getDisplayMetrics()));
    }
}

到此我们就结束了~~可能还会有一些样式上的小bug,小伙伴自己去调试哈~~ 欢迎入群!!群号:511276976

Android订单流程view(超简单!)

原文:http://blog.csdn.net/vv_bug/article/details/67633707

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!