欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-06-30 08:33:30
 android 开发订单流程view实例详解 先看看最终效果图: 怎么样,效果还是很不错的吧?群里有人说切四张图的、recycleview的、各种的都有...

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

先看看最终效果图:

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()));
  }
}

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