绘制饼状图(自定义控件)

来源:互联网 发布:尼特族 知乎 编辑:程序博客网 时间:2024/06/05 09:45

效果图:

             


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >    <com.example.view.MyView        android:id="@+id/my_view"        android:layout_width="wrap_content"        android:layout_height="wrap_content"         /></RelativeLayout>



package com.example.view;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import android.util.Log;import android.view.View;@SuppressLint("DrawAllocation")public class MyView extends View {/** * 大扇形半径 */private static final int BR = 100;/** * 中等扇形半径 */private static final int MR = 90;/** * 小扇形半径 */private static final int SR = 80;/** * 开始绘制的起始角度 */private static final int START = 90;/** * 扇形圆心x坐标 */private static int CX;/** * 扇形圆心y坐标 */private static int CY;/** * 大扇形内部圆心x坐标 */private static int BX;/** * 大扇形内部圆心y坐标 */private static int BY;/** * 中等扇形内部圆心x坐标 */private static int MX;/** * 中等扇形内部圆心y坐标 */private static int MY;/** * 小扇形内部圆心x坐标 */private static int SX;/** * 小扇形内部圆心y坐标 */private static int SY;private int big;private int middle;private int small;private Float bigRO;private Float middleRO;private Float smallRO;private String moneyBig;private String moneyMiddle;private String moneySmall;/** * 大扇形角度的一半的正玄值 */private double sin2big;/** * 大扇形角度的一半的余玄值 */private double cos2big;private double sin2middle;private double cos2middle;private double sin2small;private double cos2small;public MyView(Context context) {super(context);}public MyView(Context context, AttributeSet attrs) {super(context, attrs);Log.d("ee", "MyView-----------");}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);Log.d("ee", "onMeasure-----------");}public void setRatio(Float big, Float middle, Float small, String moneyBig, String moneyMiddle, String moneySmall) {this.bigRO = big;this.middleRO = middle;this.smallRO = small;this.big = (int) (big * 0.01 * 360);this.middle = (int) (middle * 0.01 * 360);this.small = (int) (small * 0.01 * 360);this.moneyBig = moneyBig;this.moneyMiddle = moneyMiddle;this.moneySmall = moneySmall;}@SuppressLint("DrawAllocation")@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);Log.d("ee", "onDraw-----------");CX = this.getWidth() / 2;CY = this.getHeight() / 2;sin2big = Math.sin(Math.toRadians(big / 2));cos2big = Math.cos(Math.toRadians(big / 2));BX = (int) (CX - BR / 2 * sin2big);BY = (int) (CY + BR / 2 * cos2big);sin2middle = Math.sin(Math.toRadians(middle / 2));cos2middle = Math.cos(Math.toRadians(middle / 2));MX = (int) (CX + MR / 2 * sin2middle);MY = (int) (CY + MR / 2 * cos2middle);if (middle + small / 2 >= 90) {sin2small = Math.sin(Math.toRadians(small / 2 - (180 - big)));cos2small = Math.cos(Math.toRadians(small / 2 - (180 - big)));SX = (int) (CX + SR / 2 * sin2small);SY = (int) (CY - SR / 2 * cos2small);} else {sin2small = Math.sin(Math.toRadians(middle + small / 2));cos2small = -Math.cos(Math.toRadians(middle + small / 2));SX = (int) (CX + SR / 2 * sin2small);SY = (int) (CY - SR / 2 * cos2small);}/* * 方法 说明 drawRect 绘制矩形 drawCircle 绘制圆形 drawOval 绘制椭圆 drawPath 绘制任意多边形 * drawLine 绘制直线 drawPoin 绘制点 */// 创建画笔Paint p = new Paint();p.setAntiAlias(true);// 设置画笔的锯齿效果。 true是去除,大家一看效果就明白了// 绘制最大扇形p.setColor(getResources().getColor(R.color.lan));// 设置色Log.d("ee", (CX - BR) + "  " + (CY - BR) + "  " + (CX + BR) + "  " + (CY + BR));RectF oval2 = new RectF(CX - BR, CY - BR, CX + BR, CY + BR);// 设置个新的长方形,扫描测量canvas.drawArc(oval2, START, big, true, p);// 绘制中间扇形p.setColor(getResources().getColor(R.color.huang));// 设置色oval2 = new RectF(CX - MR, CY - MR, CX + MR, CY + MR);// 设置个新的长方形,扫描测量canvas.drawArc(oval2, 360 - middle + START, middle, true, p);// 绘制最小扇形p.setColor(getResources().getColor(R.color.lv));// 设置色oval2 = new RectF(CX - SR, CY - SR, CX + SR, CY + SR);// 设置个新的长方形,扫描测量canvas.drawArc(oval2, 360 + (START - middle - small), small, true, p);// 绘制中间白色圆p.setColor(getResources().getColor(R.color.bai));// 设置BAI色canvas.drawCircle(CX, CY, 20, p);// 中心圆Log.d("ee", "  CX:" + CX + "  CY:" + CY + "  BX:" + BX + "  BY:" + BY + "  big角度:" + big / 2 + "  半径BR:" + BR + "    正玄值:" + Math.sin(Math.toRadians(big / 2)) + "    " + BR * Math.sin(Math.toRadians(big / 2)) + "    " + Math.cos(Math.toRadians(big / 2)) + "    " + "    余弦值:" + BR * Math.cos(Math.toRadians(big / 2)));// 大扇形内部的白色斜线条p.setColor(getResources().getColor(R.color.bai));// 设置BAI色canvas.drawLine(BX, BY, (int) (CX - BR * sin2big), (int) (CY + BR * cos2big), p);// 大扇形外的蓝色斜线条p.setColor(getResources().getColor(R.color.lan));canvas.drawLine((int) (CX - BR * sin2big), (int) (CY + BR * cos2big), (int) (CX - (BR + 20) * sin2big), (int) (CY + (BR + 20) * cos2big), p);// 大扇形外的蓝色直线条canvas.drawLine((int) (CX - (BR + 20) * sin2big), (int) (CY + (BR + 20) * cos2big), (int) (CX - (BR + 20) * sin2big - 30), (int) (CY + (BR + 20) * cos2big), p);// 大扇形外的蓝色直线条上的百分比字体canvas.drawText(bigRO + "%", (int) (CX - (BR + 20) * sin2big - 30 + 5), (int) (CY + (BR + 20) * cos2big - 2), p);// 大扇形内部的三个叠加圆p.setColor(getResources().getColor(R.color.bai));// 设置红色canvas.drawCircle(BX, BY, 8, p);// 白圆p.setColor(getResources().getColor(R.color.lan));// 设置红色canvas.drawCircle(BX, BY, 6, p);// 蓝圆p.setColor(getResources().getColor(R.color.bai));// 设置红色canvas.drawCircle(BX, BY, 4, p);// 白圆// 大扇形内部的资金字体canvas.drawText(moneyBig, BX - 20, BY + 20, p);// 中等扇形内部的白色斜线条canvas.drawLine(MX, MY, (float) (CX + MR * sin2middle), (float) (CY + MR * cos2middle), p);// 中等扇形外的黄色斜线条p.setColor(getResources().getColor(R.color.huang));canvas.drawLine((float) (CX + MR * sin2middle), (float) (CY + MR * cos2middle), (float) (CX + (MR + 20) * sin2middle), (float) (CY + (MR + 20) * cos2middle), p);// 中等扇形外的黄色直线条canvas.drawLine((float) (CX + (MR + 20) * sin2middle), (float) (CY + (MR + 20) * cos2middle), (float) (CX + (MR + 20) * sin2middle + 50), (float) (CY + (MR + 20) * cos2middle), p);// 中等扇形外的黄色直线条上的百分比字体canvas.drawText(middleRO + "%", (float) (CX + (MR + 20) * sin2middle + 50 - 40), (float) (CY + (MR + 20) * cos2middle - 2), p);// 中等扇形内部的三个叠加圆p.setColor(getResources().getColor(R.color.bai));// 设置色Log.d("ee", middle / 2 + "  " + MR + "    " + MR / 2 * Math.sin(middle / 2) + "    " + CX + "    " + MR / 2 * Math.cos(middle / 2) + "    " + CY);canvas.drawCircle(MX, MY, 8, p);// 白圆p.setColor(getResources().getColor(R.color.huang));// 设置色canvas.drawCircle(MX, MY, 6, p);// 黄圆p.setColor(getResources().getColor(R.color.bai));// 设置色canvas.drawCircle(MX, MY, 4, p);// 白圆// 小扇形内部的资金字体canvas.drawText(moneyMiddle, MX - 20, MY + 20, p);// 小扇形内部的三个叠加圆Log.d("ee", "  CX:" + CX + "  CY:" + CY + "  SX:" + SX + "  SY:" + SY + "  small角度:" + small / 2 + "  半径SR:" + SR + "    正玄值:" + Math.sin(Math.toRadians(small / 2)) + "    " + SR * Math.sin(Math.toRadians(small / 2)) + "    " + Math.cos(Math.toRadians(small / 2)) + "    " + "    余弦值:" + SR * Math.cos(Math.toRadians(small / 2)));p.setColor(getResources().getColor(R.color.bai));// 设置色canvas.drawCircle(SX, SY, 8, p);// 白圆p.setColor(getResources().getColor(R.color.lv));// 设置色canvas.drawCircle(SX, SY, 6, p);// 黄圆p.setColor(getResources().getColor(R.color.bai));// 设置色canvas.drawCircle(SX, SY, 4, p);// 白圆// 小扇形内部的资金字体canvas.drawText(moneySmall, SX, SY + 20, p);// 小扇形内部的白色斜线条canvas.drawLine(SX, SY, (float) (CX + SR * sin2small), (float) (CY - SR * cos2small), p);// 小扇形外的蓝色斜线条p.setColor(getResources().getColor(R.color.lv));canvas.drawLine((float) (CX + SR * sin2small), (float) (CY - SR * cos2small), (float) (CX + (SR + 20) * sin2small), (float) (CY - (SR + 20) * cos2small), p);// 小扇形外的蓝色直线条canvas.drawLine((float) (CX + (SR + 20) * sin2small), (float) (CY - (SR + 20) * cos2small), (float) (CX + (SR + 20) * sin2small + 50), (float) (CY - (SR + 20) * cos2small), p);// 小扇形外的蓝色直线条上的百分比字体canvas.drawText(smallRO + "%", (float) (CX + (SR + 20) * sin2small + 50 - 40), (float) (CY - (SR + 20) * cos2small - 2), p);// canvas.drawText("画圆:", 10, 20, p);// 画文本// canvas.drawCircle(60, 20, 10, p);// 小圆// p.setAntiAlias(true);// 设置画笔的锯齿效果。 true是去除,大家一看效果就明白了// canvas.drawCircle(120, 20, 20, p);// 大圆// cx:圆心的x坐标。// cy:圆心的y坐标。// radius:圆的半径。// paint:绘制时所使用的画笔。//// canvas.drawText("画线及弧线:", 10, 60, p);// p.setColor(Color.GREEN);// 设置绿色// canvas.drawLine(60, 40, 100, 40, p);// 画线// canvas.drawLine(110, 40, 190, 80, p);// 斜线// // 画笑脸弧线// p.setStyle(Paint.Style.STROKE);// 设置空心// RectF oval1 = new RectF(150, 20, 180, 40);// canvas.drawArc(oval1, 180, 180, false, p);// 小弧形// oval1.set(190, 20, 220, 40);// canvas.drawArc(oval1, 180, 180, false, p);// 小弧形// oval1.set(160, 30, 210, 60);// canvas.drawArc(oval1, 0, 180, false, p);// 小弧形//// canvas.drawText("画矩形:", 10, 80, p);// p.setColor(Color.GRAY);// 设置灰色// p.setStyle(Paint.Style.FILL);// 设置填满// canvas.drawRect(60, 60, 80, 80, p);// 正方形// canvas.drawRect(60, 90, 160, 100, p);// 长方形// canvas.drawText("画扇形和椭圆:", 10, 120, p);// /* 设置渐变色 这个正方形的颜色是改变的 */// Shader mShader = new LinearGradient(0, 0, 100, 100, new int[] {// Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.LTGRAY },// null, Shader.TileMode.REPEAT); // 一个材质,打造出一个线性梯度沿著一条线。// p.setShader(mShader);// // p.setColor(Color.BLUE);// RectF oval2 = new RectF(60, 100, 200, 240);// 设置个新的长方形,扫描测量// canvas.drawArc(oval2, 200, 130, true, p);// oval :指定圆弧的外轮廓矩形区域。// startAngle: 圆弧起始角度,单位为度。// sweepAngle: 圆弧扫过的角度,顺时针方向,单位为度。// useCenter: 如果为True时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形。// paint: 绘制圆弧的画板属性,如颜色,是否填充等。// // 画弧,第一个参数是RectF:该类是第二个参数是角度的开始,第三个参数是多少度,第四个参数是真的时候画扇形,是假的时候画弧线// // 画椭圆,把oval改一下// oval2.set(210, 100, 250, 130);// canvas.drawOval(oval2, p);// canvas.drawText("画三角形:", 10, 200, p);// // 绘制这个三角形,你可以绘制任意多边形// Path path = new Path();// path.moveTo(80, 200);// 此点为多边形的起点// path.lineTo(120, 250);// path.lineTo(80, 250);// path.close(); // 使这些点构成封闭的多边形// canvas.drawPath(path, p);//// // 你可以绘制很多任意多边形,比如下面画六连形// p.reset();// 重置// p.setColor(Color.LTGRAY);// p.setStyle(Paint.Style.STROKE);// 设置空心// Path path1 = new Path();// path1.moveTo(180, 200);// path1.lineTo(200, 200);// path1.lineTo(210, 210);// path1.lineTo(200, 220);// path1.lineTo(180, 220);// path1.lineTo(170, 210);// path1.close();// 封闭// canvas.drawPath(path1, p);// /*// * Path类封装复合(多轮廓几何图形的路径// * 由直线段*、二次曲线,和三次方曲线,也可画以油画。drawPath(路径、油漆),要么已填充的或抚摸// * (基于油漆的风格),或者可以用于剪断或画画的文本在路径。// *///// // 画圆角矩形// p.setStyle(Paint.Style.FILL);// 充满// p.setColor(Color.LTGRAY);// p.setAntiAlias(true);// 设置画笔的锯齿效果// canvas.drawText("画圆角矩形:", 10, 260, p);// RectF oval3 = new RectF(80, 260, 200, 300);// 设置个新的长方形// canvas.drawRoundRect(oval3, 20, 15, p);// 第二个参数是x半径,第三个参数是y半径//// // 画贝塞尔曲线// canvas.drawText("画贝塞尔曲线:", 10, 310, p);// p.reset();// p.setStyle(Paint.Style.STROKE);// p.setColor(Color.GREEN);// Path path2 = new Path();// path2.moveTo(100, 320);// 设置Path的起点// path2.quadTo(150, 310, 170, 400); // 设置贝塞尔曲线的控制点坐标和终点坐标// canvas.drawPath(path2, p);// 画出贝塞尔曲线//// // 画点// p.setStyle(Paint.Style.FILL);// canvas.drawText("画点:", 10, 390, p);// canvas.drawPoint(60, 390, p);// 画一个点// canvas.drawPoints(new float[] { 60, 400, 65, 400, 70, 400 }, p);//// 画多个点//// // 画图片,就是贴图// Bitmap bitmap = BitmapFactory.decodeResource(getResources(),// R.drawable.ic_launcher);// canvas.drawBitmap(bitmap, 250, 360, p);}}

package com.example.view;import android.os.Bundle;import android.app.Activity;import android.view.Menu;public class MainActivity extends Activity {private MyView myView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myView = (MyView) findViewById(R.id.my_view);myView.setRatio(50f, 30f, 20f, "$50000", "$30000", "$20000");}}





0 0