android自定义控件之折线图

最近在学着做android自定义控件,为熟练Canvas与Paint的使用方法而写了个折线图控件。效果如下:

图中的X轴刻度数、Y轴的刻度数、折现数、以及折现数据都做了参数供调用者指定。废话不多了,直接上控件代码

package com.example.customwidget;

import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;

/**
 * 折线图控件
 * 
 * @author 轻指飞扬
 * @version 1.0
 */
public class LineChart extends View {

	Typeface font = Typeface.create("宋体", Typeface.NORMAL);
	Typeface blodFont = Typeface.create("宋体", Typeface.BOLD);

	private CharInfo charInfo;//图表信息
	private List<LineInfo> lineInfos;//折线信息

	public LineChart(Context context) {
		super(context);
	}

	public LineChart(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
	}

	public LineChart(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		Paint paint = new Paint();
		paint.setColor(Color.WHITE);
		paint.setTextSize(20);
		paint.setTypeface(blodFont);
		canvas.drawText(charInfo.getTitle(), 100, 20, paint);
		// canvas.drawText("最近24小时空气质量指数", 100, 20, paint);

		int ySpliteNum = charInfo.getyScaleNum();
		int xSpliteNum = charInfo.getxScaleNum();
		// int ySpliteNum = 6;
		// int xSpliteNum = 6;

		// X轴信息
		int xLineXStartCoord = this.getLeft() + 12;
		int xLineXEndCoord = this.getRight() - 50;
		int xLineYStartCoord = this.getBottom() - 70;
		int xLineYEndCoord = xLineYStartCoord;
		int xLineLength = xLineXEndCoord - xLineXStartCoord;

		// Y轴信息
		int yLineXStartCoord = xLineXStartCoord;
		int yLineXEndCoord = xLineXStartCoord;
		int yLineYStartCoord = xLineYStartCoord;
		int yLineYEndCoord = this.getTop() + 50;
		int yLineLength = yLineYStartCoord > yLineYEndCoord == true ? yLineYStartCoord
				- yLineYEndCoord
				: yLineYEndCoord - yLineYStartCoord;

		// 画坐标轴
		paint.setStrokeWidth(2);
		canvas.drawLine(xLineXStartCoord, xLineYStartCoord, xLineXEndCoord,
				xLineYEndCoord, paint);
		canvas.drawLine(yLineXStartCoord, yLineYStartCoord, yLineXEndCoord,
				yLineYEndCoord, paint);

		// 画X轴(时间轴)刻度
		paint.setColor(0xCCCCCCFF);
		int scale = 5;
		Integer[] xPoint = new Integer[xSpliteNum];
		int xStep = xLineLength / xSpliteNum;
		int xLine = xLineXStartCoord;
		for (int i = 0; i < xSpliteNum; i++) {
			xLine += xStep;
			xPoint[i] = xLine;
			canvas.drawLine(xLine, xLineYStartCoord + scale, xLine,
					xLineYEndCoord - scale, paint);
		}
		String[] xScaleDownLabel = charInfo.getxScaleDownLable();
		for (int i = 0; i < xPoint.length; i++) {
			paint.setColor(Color.WHITE);
			paint.setTextSize(14);
			paint.setTypeface(font);
			paint.setTextAlign(Align.RIGHT);
			if (i == 0) {
				canvas.drawText(xScaleDownLabel[i], yLineXStartCoord,
						xLineYStartCoord + 15, paint);
				canvas.drawText(xScaleDownLabel[i + 1], xPoint[i],
						xLineYStartCoord + 15, paint);
			} else {
				canvas.drawText(xScaleDownLabel[i + 1], xPoint[i],
						xLineYStartCoord + 15, paint);
			}
		}

		String[] yScaleLeftLabel = charInfo.getyScaleLeftLable();
		String[] yScaleRightLabel = charInfo.getyScaleRightLable();
		// Y轴划分
		Integer[] yPoint = new Integer[ySpliteNum];
		int yStep = yLineLength / ySpliteNum;
		int yLine = yLineYStartCoord;
		for (int i = 0; i < ySpliteNum; i++) {
			if (i == ySpliteNum - 1) {
				yLine = yLineYEndCoord;
			} else {
				yLine -= yStep;
			}
			yPoint[i] = yLine;
			canvas.drawLine(yLineXStartCoord, yLine, yLineXStartCoord
					+ xLineLength, yLine, paint);
		}

		// Y轴色块、数字
		for (int i = 0; i < yPoint.length; i++) {
			paint.setStrokeWidth(6);
			switch (i) {
			case 0:
				paint.setColor(Color.GREEN);
				canvas.drawLine(yLineXStartCoord, xLineYStartCoord,
						yLineXStartCoord, yPoint[i], paint);

				paint.setColor(Color.WHITE);
				paint.setTextSize(14);
				paint.setTypeface(font);
				paint.setTextAlign(Align.RIGHT);
				canvas.drawText("0", yLineXStartCoord - 6, xLineYStartCoord,
						paint);
				break;
			case 1:
				paint.setColor(Color.YELLOW);
				canvas.drawLine(yLineXStartCoord, yPoint[i - 1],
						yLineXStartCoord, yPoint[i], paint);
				break;
			case 2:
				paint.setColor(0xFFFF7E00);
				canvas.drawLine(yLineXStartCoord, yPoint[i - 1],
						yLineXStartCoord, yPoint[i], paint);
				break;
			case 3:
				paint.setColor(Color.RED);
				canvas.drawLine(yLineXStartCoord, yPoint[i - 1],
						yLineXStartCoord, yPoint[i], paint);
				break;
			case 4:
				paint.setColor(0xFF8E1752);
				canvas.drawLine(yLineXStartCoord, yPoint[i - 1],
						yLineXStartCoord, yPoint[i], paint);
				break;
			case 5:
				paint.setColor(0xFF781631);
				canvas.drawLine(yLineXStartCoord, yPoint[i - 1],
						yLineXStartCoord, yPoint[i], paint);
				break;
			default:
				break;
			}
			paint.setColor(Color.WHITE);
			paint.setTextSize(14);
			paint.setTypeface(font);
			paint.setTextAlign(Align.RIGHT);
			canvas.drawText(yScaleLeftLabel[i], yLineXStartCoord - 6,
					yPoint[i], paint);
			paint.setTextAlign(Align.LEFT);
			if (i == 0) {
				canvas.drawText(yScaleRightLabel[i], yLineXStartCoord + 6,
						(xLineYStartCoord + yPoint[i]) / 2, paint);
			} else {
				canvas.drawText(yScaleRightLabel[i], yLineXStartCoord + 6,
						(yPoint[i - 1] + yPoint[i]) / 2, paint);
			}
		}

		// 绘制折现
		float stepX = (float) xLineLength / 25.0f;
		float lowStepY = (float) (yLineLength - (yStep * 2)) / 200.0f;
		float middleStepY = (float) yStep / 100.0f;
		float highStepY = (float) yStep / 200.0f;
		for (int z = 0; z < lineInfos.size(); z++) {
			LineInfo lineInfo = lineInfos.get(z);

			int lastStepX = -1;
			int lastStepY = -1;
			for (int j = 0; j < lineInfo.getPoints().length; j++) {
				// 确定点的位置
				int pointX = xLineXStartCoord + (int) (j * stepX);
				int pointY = 0;
				if (lineInfo.getPoints()[j] >= 500) {
					pointY = yLineYEndCoord;
				} else if (lineInfo.getPoints()[j] >= 200) {
					if (lineInfo.getPoints()[j] > 300) {
						int high = lineInfo.getPoints()[j] - 300;
						pointY += (high * highStepY);
						pointY += (100 * middleStepY);
					} else {
						int middle = lineInfo.getPoints()[j] - 200;
						pointY += (middle * middleStepY);
					}
					pointY += (200 * lowStepY);
					pointY = yLineYStartCoord - pointY;
				} else {
					pointY = yLineYStartCoord
							- (int) (lowStepY * lineInfo.getPoints()[j]);
				}

				// 画点
				paint.setColor(lineInfo.getPointColor());
				canvas.drawCircle(pointX, pointY, 3, paint);

				// 连线
				if (lastStepX != -1 && lastStepY != -1) {
					paint.setColor(lineInfo.getLineColor());
					paint.setStrokeWidth(1.5f);
					canvas.drawLine(lastStepX, lastStepY, pointX, pointY, paint);
				}

				// 记录
				lastStepX = pointX;
				lastStepY = pointY;
			}

			// 在图表画折现标识
			int markY = this.getBottom() - 40;
			int markX = xLineXStartCoord
					+ (xLineLength / (lineInfos.size() + 1)) * (z + 1) - 30;

			paint.setColor(lineInfo.getPointColor());
			canvas.drawCircle(markX, markY, 3, paint);
			paint.setColor(lineInfo.getLineColor());
			paint.setStrokeWidth(1.5f);
			canvas.drawLine(markX - 10, markY, markX + 10, markY, paint);
			paint.setColor(Color.WHITE);
			paint.setTextAlign(Align.LEFT);
			canvas.drawText(lineInfo.getName(), markX + 10, markY + 5, paint);
		}

	}

	public CharInfo getCharInfo() {
		return charInfo;
	}

	public void setCharInfo(CharInfo charInfo) {
		this.charInfo = charInfo;
	}

	public List<LineInfo> getLineInfos() {
		return lineInfos;
	}

	public void setLineInfos(List<LineInfo> lineInfos) {
		this.lineInfos = lineInfos;
	}

}

 控件调用:

package com.example.customwidget;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		LineChart lineChart = (LineChart) findViewById(R.id.lineChart);
		
		CharInfo charInfo = new CharInfo();
		charInfo.setTitle("最近24小时空气质量指数");
		charInfo.setxScaleNum(6);
		charInfo.setyScaleNum(6);
		String[] yScaleLeftLable = new String[6];
		yScaleLeftLable[0] = "50";
		yScaleLeftLable[1] = "100";
		yScaleLeftLable[2] = "150";
		yScaleLeftLable[3] = "200";
		yScaleLeftLable[4] = "300";
		yScaleLeftLable[5] = "500";
		charInfo.setyScaleLeftLable(yScaleLeftLable);
		String[] yScaleRightLable = new String[6];
		yScaleRightLable[0] = "优";
		yScaleRightLable[1] = "良";
		yScaleRightLable[2] = "轻度污染";
		yScaleRightLable[3] = "中度污染";
		yScaleRightLable[4] = "重度污染";
		yScaleRightLable[5] = "严重污染";
		charInfo.setyScaleRightLable(yScaleRightLable);
		String[] xScaleDownLable = new String[7];
		xScaleDownLable[0] = "21:00";
		xScaleDownLable[1] = "01:00";
		xScaleDownLable[2] = "05:00";
		xScaleDownLable[3] = "09:00";
		xScaleDownLable[4] = "13:00";
		xScaleDownLable[5] = "17:00";
		xScaleDownLable[6] = "21:00";
		charInfo.setxScaleDownLable(xScaleDownLable);
		
		lineChart.setCharInfo(charInfo);
		
		List<LineInfo> lineInfos = new ArrayList<LineInfo>();
		
		LineInfo lineInfo1 = new LineInfo();
		lineInfo1.setPointColor(0xFFE5B814);
		lineInfo1.setLineColor(0xFFC8A724);
		lineInfo1.setName("美国领事馆");
		lineInfo1.setPoints(new int[]{570,450,350,250,130,
				170,190,185,177,165,155,150,168,170,190,
				200,210,205,230,220,210,190,180,190,170,
				180});
		lineInfos.add(lineInfo1);
		
		LineInfo lineInfo2 = new LineInfo();
		lineInfo2.setPointColor(0xFF06D606);
		lineInfo2.setLineColor(0xFF99CC00);
		lineInfo2.setName("静安监测站");
		lineInfo2.setPoints(new int[]{170,150,250,300,170,
				120,130,165,147,265,255,170,268,180,160,
				240,220,215,200,210,240,180,190,200,270,
				190});
		lineInfos.add(lineInfo2);
		
		lineChart.setLineInfos(lineInfos);
		
		
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

 附:两个Bean

package com.example.customwidget;

import java.util.List;

public class CharInfo {
	private String title;
	private int yScaleNum;
	private String[] yScaleLeftLable;
	private String[] yScaleRightLable;
	private int xScaleNum;
	private String[] xScaleUpLable;
	private String[] xScaleDownLable;
	private List<LineInfo> lineInfos;

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public int getyScaleNum() {
		return yScaleNum;
	}

	public void setyScaleNum(int yScaleNum) {
		this.yScaleNum = yScaleNum;
	}

	public String[] getyScaleLeftLable() {
		return yScaleLeftLable;
	}

	public void setyScaleLeftLable(String[] yScaleLeftLable) {
		this.yScaleLeftLable = yScaleLeftLable;
	}

	public String[] getyScaleRightLable() {
		return yScaleRightLable;
	}

	public void setyScaleRightLable(String[] yScaleRightLable) {
		this.yScaleRightLable = yScaleRightLable;
	}

	public int getxScaleNum() {
		return xScaleNum;
	}

	public void setxScaleNum(int xScaleNum) {
		this.xScaleNum = xScaleNum;
	}

	public String[] getxScaleUpLable() {
		return xScaleUpLable;
	}

	public void setxScaleUpLable(String[] xScaleUpLable) {
		this.xScaleUpLable = xScaleUpLable;
	}

	public String[] getxScaleDownLable() {
		return xScaleDownLable;
	}

	public void setxScaleDownLable(String[] xScaleDownLable) {
		this.xScaleDownLable = xScaleDownLable;
	}

	public List<LineInfo> getLineInfos() {
		return lineInfos;
	}

	public void setLineInfos(List<LineInfo> lineInfos) {
		this.lineInfos = lineInfos;
	}

}
package com.example.customwidget;

public class LineInfo {
	private String name;
	private int pointColor;
	private int lineColor;
	private int[] points;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPointColor() {
		return pointColor;
	}

	public void setPointColor(int pointColor) {
		this.pointColor = pointColor;
	}

	public int getLineColor() {
		return lineColor;
	}

	public void setLineColor(int lineColor) {
		this.lineColor = lineColor;
	}

	public int[] getPoints() {
		return points;
	}

	public void setPoints(int[] points) {
		this.points = points;
	}

}

OK,That's all!

猜你喜欢

转载自johnnyg.iteye.com/blog/2010733