Android Canvas练习(2)自已绘饼图(Pie Chart)

    上文弄了个绘制报表的,有了报表,当然想一并也绘个饼图,柱形图之类的玩玩,看看了API,觉得应当很简单,饼图实现了下,

实现代码确实也很简单,Android的这些函数封装的确实好用。

     

   效果图如下:

       

      不过实现过程还是比较曲折的,首先碰到一个sdk的bug,drawTextOnPath()用法明明是对的,但老是不显示没效果,后面

才查到,这个是BUG,后来在http://blog.csdn.net/yanzi1225627/article/details/8583066 上查到解决方法是在view的构造函数里设置this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);  才算能继续下去。


 先附上完整的实现代码:       
package com.xcl.chart;

/**
 * Canvas练习 
 * 	  自已画饼图,实现出来后觉得也算实用.
 *   
 * author:xiongchuanliang
 * date:2014-4-6
 */

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.DisplayMetrics;
import android.view.View;

@SuppressLint("NewApi")
public class PanelPieChart1 extends View {
	
	private int ScrHeight;
	private int ScrWidth;
					
	private Paint[] arrPaintArc;
	private Paint PaintText = null;
	/*
	final int[] colors = new int[]{			
			R.color.red,
			R.color.white,
			R.color.green,
			R.color.yellow,
			R.color.blue,				
		};*/
	
	//RGB颜色数组
	private final int arrColorRgb[][] = { {77, 83, 97},  
							              {148, 159, 181},  
							              {253, 180, 90},
							              {52, 194, 188},
							              {39, 51, 72},
							              {255, 135, 195},
							              {215, 124, 124},
							              {180, 205, 230}} ;
	
	//演示用的比例,实际使用中,即为外部传入的比例参数
	final float arrPer[] = new float[]{20f,30f,10f,40f};
	
	public PanelPieChart1(Context context){
		super(context);
		
		//解决4.1版本 以下canvas.drawTextOnPath()不显示问题			
		this.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
		
		//屏幕信息
		DisplayMetrics dm = getResources().getDisplayMetrics();
		ScrHeight = dm.heightPixels;
		ScrWidth = dm.widthPixels;
					
		//设置边缘特殊效果
	    BlurMaskFilter PaintBGBlur = new BlurMaskFilter(
	    						1, BlurMaskFilter.Blur.INNER);

		arrPaintArc = new Paint[5];	
		//Resources res = this.getResources();
		for(int i=0;i<5;i++)
		{
			arrPaintArc[i] = new Paint();			
			//arrPaintArc[i].setColor(res.getColor(colors[i] )); 
			arrPaintArc[i].setARGB(255, arrColorRgb[i][0], arrColorRgb[i][1], arrColorRgb[i][2]);
			arrPaintArc[i].setStyle(Paint.Style.FILL);
			arrPaintArc[i].setStrokeWidth(4);
			arrPaintArc[i].setMaskFilter(PaintBGBlur);
		}
			
		PaintText = new Paint();
		PaintText.setColor(Color.BLUE);
		PaintText.setTextSize(22);
		//PaintText.setTypeface(Typeface.DEFAULT_BOLD);
	}
	
	public void onDraw(Canvas canvas){
		//画布背景
		canvas.drawColor(Color.WHITE);
		
		float cirX = ScrWidth / 2;
		float cirY = ScrHeight / 3 ;
		float radius = ScrHeight / 5 ;//150;
		//先画个圆确定下显示位置
		//canvas.drawCircle(cirX,cirY,radius,PaintArcRed);
								
		float arcLeft = cirX - radius;
		float arcTop  = cirY - radius ;
		float arcRight = cirX + radius ;
		float arcBottom = cirY + radius ;
		RectF arcRF0 = new RectF(arcLeft ,arcTop,arcRight,arcBottom);	
		
		Path pathArc=new Path();   		    			    
		// x,y,半径 ,CW
		pathArc.addCircle(cirX,cirY,radius,Direction.CW); 
		    //绘出饼图大轮廓
		canvas.drawPath(pathArc,arrPaintArc[0]);
	 
		float CurrPer = 0f; //偏移角度
		float Percentage =  0f; //当前所占比例
								
		int scrOffsetW = ScrWidth - 200;
		int scrOffsetH = ScrHeight - 300;
		int scrOffsetT = 40;
							
		//Resources res = this.getResources();			
		int i= 0;
		for(i=0; i<3; i++) //注意循环次数噢
		{
			//将百分比转换为饼图显示角度
			Percentage = 360 * (arrPer[i]/ 100);
			Percentage = (float)(Math.round(Percentage *100))/100;
			 
			//在饼图中显示所占比例
			canvas.drawArc(arcRF0, CurrPer, Percentage, true, arrPaintArc[i+2]); 
			
			//当前颜色
			canvas.drawRect(scrOffsetW ,scrOffsetH + i * scrOffsetT,
					scrOffsetW + 60 ,scrOffsetH - 30 + i * scrOffsetT, arrPaintArc[i+2]);
			//当前比例	
			canvas.drawText(String.valueOf(arrPer[i]) +"%",
					scrOffsetW + 70,scrOffsetH + i * scrOffsetT, PaintText);
			//下次的起始角度
			CurrPer += Percentage;
		}
		
		//最末尾比例说明
		canvas.drawRect(scrOffsetW ,scrOffsetH + i * scrOffsetT,
				scrOffsetW + 60 ,scrOffsetH - 30 + i * scrOffsetT, arrPaintArc[0]);
			
		canvas.drawText(String.valueOf(arrPer[i]) +"%",
				scrOffsetW + 70,scrOffsetH + i * scrOffsetT, PaintText);

		//Demo的作者信息
		canvas.drawText("author:xcl",
				70,scrOffsetH + i+1 * scrOffsetT, PaintText);
		canvas.drawText("date:2014-4-7",
				70,scrOffsetH + i * scrOffsetT, PaintText);			
		
	}		
}


 代码注释算比较详细,就不多说了,主要整理下我实现过程中了解到的一些使用方法.

      RectF  定义矩形,这个用得很多,定坐标时,脑子中一定要有一个清楚的印象,示意图如下:

           

            要是在实现时确定不了,可以用 canvas.drawRect(new RectF(left, top, right bottm), paint);  在屏幕上画出来看看效果。

       Path: 官网Doc 

             这个在可以先用下面的代码看看效果:            

Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
Path p = new Path();
p.moveTo(20,20);
p.lineTo(100,200);
p.lineTo(200,100);
p.lineTo(240,155);
canvas.drawPath(p,paint);
     效果如下:

         

   path不断可以画线,还可以有特殊的用法:    


   其实现代码如下:           

float cirX = ScrWidth / 2;
			float cirY = ScrHeight / 3 ;
			float radius = ScrHeight / 5 ;
			
		    Path pathArc=new Path();   		    			    
			// x,y,半径 ,CW为顺时针绘制
			pathArc.addCircle(cirX,cirY,radius,Direction.CW); 

		    canvas.drawPath(pathArc,arrPaintArc[0]);
		    canvas.drawTextOnPath("环绕文字",pathArc,0,30,PaintText); //在路径上绘制文字
     对path,如果不确实效果,可以用drawPath打印出来看看,如果打印出来是一片空白,则有可能是你输入的位置参数不正确所致


drawTextOnPath 函数原型:

          drawTextOnPath (String text,Path ath,float hOffset,float vOffset,Pating paint)

        这个函数能让文字跟着path跑,hOffset参数指定水平偏移 vOffset参数指定垂直偏移量是多少。


     drawArc()函数画圆弧的,一个最典型的用法如下:

 canvas.drawArc(new RectF(0, 0, 128, 128), 0,120, true, new Paint(
		    		Paint.ANTI_ALIAS_FLAG));
           饼图百分比的扇形图主要就是用它来实现的。


还有一个Style属性要说下,它决定了是空心,还是实心之类。
    Paint.Style.STROKE:Only draw the outline of the shapes
    Paint.Style.FILLE:Only fill the shapes
    Paint.Style.FILL_AND_STROKE:Fill and draw the outline of the shapes

大致就这些了。

  

 附其它绘制图表的链接:
      Android Canvas练习(1)画一张报表来玩
      Android Canvas练习(2)自已绘饼图
      Android Canvas练习(3)自已绘柱形图

     Android Canvas练习(4)自已绘折线图

    

MAIL: xcl_168@aliyun.com

BLOG: http://blog.csdn.net/xcl168


  


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值