当前位置: 移动技术网 > IT编程>移动开发>Android > Android 开发订单流程view实例详解

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

影讯,魔兽剑圣异界纵横5200,怪兽电力公司国语

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

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网