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程序设计有所帮助。

(0)

相关推荐

  • Android中Canvas的常用方法总结

    一.对Canvas进行操作 对Canvas的一系列操作,是指对Canvas进行旋转.平移.缩放等操作. 这些操作可以让Canvas对象使用起来更加便捷. 二.Canvas平移 /** * 画布向(100,50)方向平移 * * 参数1: 向X轴方向移动100距离 * 参数2: 向Y轴方向移动50距离 */ canvas.translate(100, 50); 三.Canvas缩放 /** * 在X轴方向放大为原来2倍,Y轴方向方大为原来的4倍 * 参数1: X轴的放大倍数 * 参数2: Y轴的放

  • Android画图之抗锯齿paint和Canvas两种方式实例

    在画图的时候,图片如果旋转或缩放之后,总是会出现那些华丽的锯齿.其实Android自带了解决方式. 方法一:给Paint加上抗锯齿标志.然后将Paint对象作为参数传给canvas的绘制方法. paint.setAntiAlias(true); 方法二:给Canvas加上抗锯齿标志. 有些地方不能用paint的,就直接给canvas加抗锯齿,更方便. 复制代码 代码如下: canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_AL

  • Android编程之OpenGL绘图技巧总结

    本文实例讲述了Android编程之OpenGL绘图技巧.分享给大家供大家参考,具体如下: 很久不用OpenGL ES绘图,怕自己忘记了,于是重新复习一遍,顺便原理性的东西总结如下: 1. Android 3D坐标系统 如图: Android的三维坐标系统中: 坐标原点位于中央, X轴从左向右延伸,原点左边的值为负数,右边为正数: Y轴从下向上延伸,原点下边的值为负数,上边为正数: Z轴屏幕里面向外面延伸,屏幕里面为负数,外面为正数. 2. 开发工具(OpenGL和OpenGL ES)介绍 Ope

  • Android编程之canvas绘制各种图形(点,直线,弧,圆,椭圆,文字,矩形,多边形,曲线,圆角矩形)

    本文实例讲述了Android编程之canvas绘制各种图形的方法.分享给大家供大家参考,具体如下: 1.首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into

  • Android编程实现canvas绘制柱状统计图功能【自动计算宽高及分度值、可左右滑动】

    本文实例讲述了Android编程实现canvas绘制柱状统计图功能.分享给大家供大家参考,具体如下: 这里实现了一个简单的柱状统计图,如下:   特点: 1.根据数据源自动计算每个条目的高度.宽度.间距,自动计算分度值. 2.当条目数较多时,可左右滑动查看全部内容,图形.文字同步滑动,并且松手后会渐渐的停下来(而不是立刻停下来). 代码: (1)核心代码:BarChartView.Java package com.sina.appbarchart; import android.app.Acti

  • Android自定义View绘图实现渐隐动画

    实现了一个有趣的小东西:使用自定义View绘图,一边画线,画出的线条渐渐变淡,直到消失.效果如下图所示: 用属性动画或者渐变填充(Shader)可以做到一笔一笔的变化,但要想一笔渐变(手指不抬起边画边渐隐),没在Android中找到现成的API可用.所以,自己做了一个. 基本的想法是这样的: •在View的onTouchEvent中记录触摸点,生成一条一条的线LineElement,放在一个List中.给每个LineElement配置一个Paint实例. •在onDraw中绘制线段. •变换Li

  • Android中使用Canvas绘制南丁格尔玫瑰图(Nightingale rose diagram)

    南丁格尔玫瑰图 在常规图表中实在很惊艳,但我初看没看懂,一查原来南丁格尔这么伟大,确实值得尊敬. 再仔细研究了下这种图的构成,发现原来就是把柱形图的柱形换成了扇形图的半径来表示,当然,变种有好多,我这只是说我理解的这种. 知道了其构成方式后就好实现了,依传入参数个数决定其扇形角度,依百分比决定其扇形的半径长度,然后就一切都水到渠成了. 漂亮的美图献上: 附上实现代码: package com.xcl.chart; /** * Canvas练习 * 自已画南丁格尔玫瑰图(Nightingale r

  • Android使用Canvas绘制圆形进度条效果

    前言 Android自定义控件经常会用到Canvas绘制2D图形,在优化自己自定义控件技能之前,必须熟练掌握Canvas绘图机制.本文从以下三个方面对Canvas绘图机制进行讲解: 画布Canvas 画笔Paint 示例圆形进度条 画布Canvas 首先,来看一下Android官网对Canvas类的定义: The Canvas class holds the "draw" calls.To draw something, you need 4 basic components: A B

  • Android编程之绘图canvas基本用法示例

    本文实例讲述了Android编程之绘图canvas基本用法.分享给大家供大家参考,具体如下: MainActivity的代码如下: package example.com.myapplication; import android.os.Bundle; import android.app.Activity; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedIns

  • Android编程开发之在Canvas中利用Path绘制基本图形(圆形,矩形,椭圆,三角形等)

    本文实例讲述了Android编程开发之在Canvas中利用Path绘制基本图形的方法.分享给大家供大家参考,具体如下: 在Android中绘制基本的集合图形,本程序就是自定义一个View组件,程序重写该View组件的onDraw(Canvase)方法,然后在该Canvas上绘制大量的基本的集合图形. 直接上代码: 1.自定义的View组件代码: package com.infy.configuration; import android.content.Context; import andro

  • Android 游戏开发之Canvas画布的介绍及方法

    Canvas,在英语中,这个单词的意思是帆布.在Android中,则把Canvas当做画布,只要我们借助设置好的画笔(Paint类)就可以在画布上绘制我们想要的任何东西:另外它也是显示位图(Bitmap类)的核心类.随用户的喜好,Canvas还可设置一些关于画布的属性,比如,画布的颜色.尺寸等.Canvas提供了如下一些方法:    Canvas(): 创建一个空的画布,可以使用setBitmap()方法来设置绘制具体的画布.    Canvas(Bitmap bitmap): 以bitmap对

  • Android 通过onDraw实现在View中绘图操作的示例

    Android绘图操作,通过继承View实现,在onDraw函数中实现绘图.下面是一个简单的例子: 复制代码 代码如下: public class AndroidTest extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(save

随机推荐