首页 > 系统 > Android > 正文

Android 开发订单流程view实例详解

2019-12-12 03:15:18
字体:
来源:转载
供稿:网友

 Android 开发订单流程view实例详解

先看看最终效果图:

怎么样,效果还是很不错的吧?群里有人说切四张图的、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()));  }}

 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表