当前位置: 移动技术网 > IT编程>移动开发>Android > Android view自定义带文字带进度的控件

Android view自定义带文字带进度的控件

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

asuka博客,ted演讲是什么,p2p播放器下载

目标:自定义一个带文字带进度的控件,具体内容如下

效果图:

不啰嗦先看东西:

步骤分析

提取自定义属性

//提供对外暴露的属性,如有不够自己扩展
  <declare-styleable name="descprogressview">
    <attr name="dpv_text_normal_color" format="color" />
    <attr name="dpv_text_seleced_color" format="color" />
    <attr name="dpv_text_size" format="dimension" />
    <attr name="dev_progress_bg_color" format="color" />
    <attr name="dev_progress_small_circle_color" format="color" />
    <attr name="dev_progress_big_circle_color" format="color" />
  </declare-styleable>

解析自定义属性

private void initattrs(context context, @nullable attributeset attrs, int defstyleattr) {
    typedarray typedarray = context.gettheme().obtainstyledattributes(attrs, r.styleable.descprogressview, defstyleattr, r.style.def_descprogressviewstyle);
    int indexcount = typedarray.getindexcount();
    for (int i = 0; i < indexcount; i++) {
      int attr = typedarray.getindex(i);
      switch (attr) {
        case r.styleable.descprogressview_dpv_text_normal_color:
          textnormalcolor = typedarray.getcolor(attr, color.black);
          break;
        case r.styleable.descprogressview_dpv_text_seleced_color:
          textselectedcolor = typedarray.getcolor(attr, color.black);
          break;
        case r.styleable.descprogressview_dpv_text_size:
          dpvtextsize = typedarray.getdimensionpixelsize(attr, 0);
          break;
        case r.styleable.descprogressview_dev_progress_bg_color:
          dpvprogressbgcolor = typedarray.getcolor(attr, color.black);
          break;
        case r.styleable.descprogressview_dev_progress_small_circle_color:
          dpvsmallciclecolor = typedarray.getcolor(attr, color.black);
          break;
        case r.styleable.descprogressview_dev_progress_big_circle_color:
          dpvbigcirclecolor = typedarray.getcolor(attr, color.black);
          break;
      }
    }
    typedarray.recycle();
  }

测量ui图的比例(包含图标大小比例,位置比例)

//这里大家可以根据自己的习惯来,我习惯用view的尺寸当做参照,来约束界面的view,各有利弊,也可以暴露出属性设置具体的dp值,根据比例的话,调整好比例后,所有的绘制内容会统一约束
  private static final float scale_of_progress_height = 70.f / 120;
  private static final float scale_of_top_and_bottom_padding = 10.f / 120;
  private static final float scale_of_left_and_right_padding = 20.f / 120;
  private static final float scale_of_text_desc_container = 50.f / 120;
  private static final float scale_of_big_circle_height = 22.f / 120;
  private static final float scale_of_small_circle_height = 16.f / 120;
  private static final float scale_of_line_height = 4.f / 120;
  private static final float def_view_height = 120.f;

提取绘制的各个元素的位置属性坐标等

这个view的唯一要提前确定的就是文字的位置,文字的位置确定需要知道所有文字的长度,左右间距,计算出中间的白色间隔
代码如下

 /**
   * 获取文字在画布中的位置
   */
  private void getdesctextregonpoint() {
    for (int i = 0; i < descs.size(); i++) {
      point textregonpoint = new point();
      int sumx = 0;
      //非常重要:计算各个文字在view中的具体坐标,体会下这个二级for循环,子循环是确定每个描述文本的位置
      for (int j = 0; j < i; j++) {
        point tempsum = alldesctextpoints.get(j);
        sumx += tempsum.x;
      }
      sumx += i * gettextdescspace();
      textregonpoint.x = sumx + leftandrightpadding;
      textregonpoint.y = dpviewheight - topandbottompadding - textdesccontainerheight / 2;
      textpoints4draw.add(textregonpoint);
    }
  }
 /**
   * 获取文字的间距
   *
   * @return 获取文字的间距
   */
  private float gettextdescspace() {
    float alldescwith = 0;
    for (point tempdesc : alldesctextpoints) {
      alldescwith += tempdesc.x;
    }
    int textcontainerw = (int) (dpviewwidth - leftandrightpadding * 2 - alldescwith);
    if (descs != null && descs.size() > 1) {
      int spacecount = descs.size() - 1;
      return textcontainerw * 1.f / spacecount;
    }
    return 0;
  }

绘制

我们在view测量确定了尺寸完毕之后,直接绘制即可

 @override
  protected void onsizechanged(int w, int h, int oldw, int oldh) {
  // 确定各个比例的大小
    super.onsizechanged(w, h, oldw, oldh);
    dpviewheight = h;
    dpviewwidth = w;
    progresscontainerheight = (int) (scale_of_progress_height * dpviewheight);
    topandbottompadding = (int) (scale_of_top_and_bottom_padding * dpviewheight);
    leftandrightpadding = (int) (scale_of_left_and_right_padding * dpviewheight);
    textdesccontainerheight = (int) (scale_of_text_desc_container * dpviewheight);
    smallcircleradio = (int) (scale_of_small_circle_height * dpviewheight / 2);
    bigcircleradio = (int) (scale_of_big_circle_height * dpviewheight / 2);
    lineheight = (int) (scale_of_line_height * dpviewheight);

    // 获取各个部分所需要的约束坐标
    getdesctextwidthandheight();
    getdesctextregonpoint();
    getbglinerectf();
    getbgcirclepoints();
    getselectedrectf();
    getcolorfullrectf();
    getgrayrectf();
  }


@override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  drawdesctext(canvas);
  drawbgline(canvas);
  drawselectedline(canvas);
  drawgrayrectf(canvas);
  drawselectedcircles(canvas);
 }
//绘制部分的代码就是canvas 的api的使用,没有什么技术含量.
//最后暴露给外面设置数据的接口

public void setprogressdescs(list<string> descs, int currentselectposition) {
  this.currentselectposition = currentselectposition;
  if (descs != null && descs.size() > 1) {
   this.descs.clear();
   this.descs.addall(descs);
   this.alldesctextpoints.clear();
   invalidate();
  }
 }

源代码下载地址https://github.com/guofeilong/descpbview来个star就更好了谢谢!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

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

相关文章:

验证码:
移动技术网