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

Android编程实现canvas绘制饼状统计图功能示例【自动适应条目数量与大小】

程序员文章站 2024-02-14 16:35:40
本文实例讲述了android编程实现canvas绘制饼状统计图功能。分享给大家供大家参考,具体如下: 本例的目的是实现一个简单的饼状统计图,效果如下:  &n...

本文实例讲述了android编程实现canvas绘制饼状统计图功能。分享给大家供大家参考,具体如下:

本例的目的是实现一个简单的饼状统计图,效果如下:

Android编程实现canvas绘制饼状统计图功能示例【自动适应条目数量与大小】 Android编程实现canvas绘制饼状统计图功能示例【自动适应条目数量与大小】 Android编程实现canvas绘制饼状统计图功能示例【自动适应条目数量与大小】

特点:

1.使用非常方便,可放在xml布局文件中,然后在代码中设置内容,即:

piechartview piechartview = (piechartview) findviewbyid(r.id.pie_chart);
piechartview.pieitembean[] items = new piechartview.pieitembean[]{
    new piechartview.pieitembean("娱乐", 200),
    new piechartview.pieitembean("旅行", 100),
    new piechartview.pieitembean("学习", 120),
    new piechartview.pieitembean("人际关系", 160),
    new piechartview.pieitembean("交通", 100),
    new piechartview.pieitembean("餐饮", 480)
};
piechartview.setpieitems(items);

2.条目数量,大小及折线位置,长度均自适应。左侧条目往左侧划线,右侧条目往右侧划线,文字描述与百分比居中对齐,并且文字“下划线”与文字长度自适应。对于很小的条目,将自动将折线延长以尽可能避免文字遮盖

核心代码:piechartview.java:

public class piechartview extends view {
  private int screenw, screenh;
  /**
   * the paint to draw text, pie and line.
   */
  private paint textpaint, piepaint, linepaint;
  /**
   * the center and the radius of the pie.
   */
  private int piecenterx, piecentery, pieradius;
  /**
   * the oval to draw the oval in.
   */
  private rectf pieoval;
  private float smallmargin;
  private int[] mpiecolors = new int[]{color.red, color.green, color.blue, color.yellow, color.magenta, color.cyan};
  private pieitembean[] mpieitems;
  private float totalvalue;
  public piechartview(context context) {
    super(context);
    init(context);
  }
  public piechartview(context context, attributeset attrs) {
    super(context, attrs);
    init(context);
  }
  public piechartview(context context, attributeset attrs, int defstyleattr) {
    super(context, attrs, defstyleattr);
    init(context);
  }
  private void init(context context) {
    //init screen
    screenw = screenutils.getscreenw(context);
    screenh = screenutils.getscreenh(context);
    piecenterx = screenw / 2;
    piecentery = screenh / 3;
    pieradius = screenw / 4;
    smallmargin = screenutils.dp2px(context, 5);
    pieoval = new rectf();
    pieoval.left = piecenterx - pieradius;
    pieoval.top = piecentery - pieradius;
    pieoval.right = piecenterx + pieradius;
    pieoval.bottom = piecentery + pieradius;
    //the paint to draw text.
    textpaint = new paint();
    textpaint.setantialias(true);
    textpaint.settextsize(screenutils.dp2px(context, 16));
    //the paint to draw circle.
    piepaint = new paint();
    piepaint.setantialias(true);
    piepaint.setstyle(paint.style.fill);
    //the paint to draw line to show the concrete text
    linepaint = new paint();
    linepaint.setantialias(true);
    linepaint.setstrokewidth(screenutils.dp2px(context, 1));
  }
  //the degree position of the last item arc's center.
  private float lastdegree = 0;
  //the count of the continues 'small' item.
  private int addtimes = 0;
  @override
  protected void ondraw(canvas canvas) {
    super.ondraw(canvas);
    if (mpieitems != null && mpieitems.length > 0) {
      float start = 0.0f;
      for (int i = 0; i < mpieitems.length; i++) {
        //draw pie
        piepaint.setcolor(mpiecolors[i % mpiecolors.length]);
        float sweep = mpieitems[i].getitemvalue() / totalvalue * 360;
        canvas.drawarc(pieoval, start, sweep, true, piepaint);
        //draw line away from the pie
        float radians = (float) ((start + sweep / 2) / 180 * math.pi);
        float linestartx = piecenterx + pieradius * 0.7f * (float) (math.cos(radians));
        float linestarty = piecentery + pieradius * 0.7f * (float) (math.sin(radians));
        float linestopx, linestopy;
        float rate;
        if (getoffset(start + sweep / 2) > 60) {
          rate = 1.3f;
        } else if (getoffset(start + sweep / 2) > 30) {
          rate = 1.2f;
        } else {
          rate = 1.1f;
        }
        //if the item is very small, make the text further away from the pie to avoid being hided by other text.
        if (start + sweep / 2 - lastdegree < 30) {
          addtimes++;
          rate += 0.2f * addtimes;
        } else {
          addtimes = 0;
        }
        linestopx = piecenterx + pieradius * rate * (float) (math.cos(radians));
        linestopy = piecentery + pieradius * rate * (float) (math.sin(radians));
        canvas.drawline(linestartx, linestarty, linestopx, linestopy, linepaint);
        //write text
        string itemtypetext = mpieitems[i].getitemtype();
        string itempercenttext = utility.formatfloat(mpieitems[i].getitemvalue() / totalvalue * 100) + "%";
        float itemtypetextlen = textpaint.measuretext(itemtypetext);
        float itempercenttextlen = textpaint.measuretext(itempercenttext);
        float linetextwidth = math.max(itemtypetextlen, itempercenttextlen);
        float textstartx = linestopx;
        float textstarty = linestopy - smallmargin;
        float percentstartx = linestopx;
        float percentstarty = linestopy + textpaint.gettextsize();
        if (linestartx > piecenterx) {
          textstartx += (smallmargin + math.abs(itemtypetextlen - linetextwidth) / 2);
          percentstartx += (smallmargin + math.abs(itempercenttextlen - linetextwidth) / 2);
        } else {
          textstartx -= (smallmargin + linetextwidth - math.abs(itemtypetextlen - linetextwidth) / 2);
          percentstartx -= (smallmargin + linetextwidth - math.abs(itempercenttextlen - linetextwidth) / 2);
        }
        canvas.drawtext(itemtypetext, textstartx, textstarty, textpaint);
        //draw percent text
        canvas.drawtext(itempercenttext, percentstartx, percentstarty, textpaint);
        //draw text underline
        float textlinestopx = linestopx;
        if (linestartx > piecenterx) {
          textlinestopx += (linetextwidth + smallmargin * 2);
        } else {
          textlinestopx -= (linetextwidth + smallmargin * 2);
        }
        canvas.drawline(linestopx, linestopy, textlinestopx, linestopy, linepaint);
        lastdegree = start + sweep / 2;
        start += sweep;
      }
    }
  }
  public pieitembean[] getpieitems() {
    return mpieitems;
  }
  public void setpieitems(pieitembean[] pieitems) {
    this.mpieitems = pieitems;
    totalvalue = 0;
    for (pieitembean item : mpieitems) {
      totalvalue += item.getitemvalue();
    }
    invalidate();
  }
  private float getoffset(float radius) {
    int a = (int) (radius % 360 / 90);
    switch (a) {
      case 0:
        return radius;
      case 1:
        return 180 - radius;
      case 2:
        return radius - 180;
      case 3:
        return 360 - radius;
    }
    return radius;
  }
  static class pieitembean {
    private string itemtype;
    private float itemvalue;
    pieitembean(string itemtype, float itemvalue) {
      this.itemtype = itemtype;
      this.itemvalue = itemvalue;
    }
    public string getitemtype() {
      return itemtype;
    }
    public void setitemtype(string itemtype) {
      this.itemtype = itemtype;
    }
    public float getitemvalue() {
      return itemvalue;
    }
    public void setitemvalue(float itemvalue) {
      this.itemvalue = itemvalue;
    }
  }
}

完整实例代码点击此处本站下载

更多关于android相关内容感兴趣的读者可查看本站专题:《android图形与图像处理技巧总结》、《android开发入门与进阶教程》、《android调试技巧与常见问题解决方法汇总》、《android基本组件用法总结》、《android视图view技巧总结》、《android布局layout技巧总结》及《android控件用法总结

希望本文所述对大家android程序设计有所帮助。