经过一段时间的学习(中途因事耽误一段时间),我已经能够做出一个简单的折线图控件了,现将代码放在下面,以作备忘。
这是一个可实时接收数据并显示的折线图,每次接受一个数据,图中最多可同时显示五个数据。另为转换平滑,增加了一个额外状态,即显示两个状态的中间态。
package com.example.cramile.myownviewtest;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.drawable.shapes.RoundRectShape;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import java.util.ArrayList;
/**
* Created by cramile on 2017/2/20.
*/
class myView extends View
{
//控制绘制类型
public boolean t=false;
//paint:坐标系,time:横坐标(时间),picture:折线图,point:坐标点与坐标值
Paint paint,time,picture,point;
//五个时间点,
String first ,second,third , fourth , fifth ;
//折线图绘制顶点与底点坐标
int TOP = 200;
int BOTTOM = 400;
//各坐标点的高度(Y轴)
float one = Float.MIN_VALUE;
float two = Float.MIN_VALUE;
float three = Float.MIN_VALUE;
float four = Float.MIN_VALUE;
float five = Float.MIN_VALUE;;
//各坐标点的最大(最小)值,
float Max = Float.MIN_VALUE;
float Min = Float.MIN_VALUE;
// Canvas canvas;
//初始化类
//引用了父类以及画笔初始化的方法
public myView(Context context)
{
this(context,null);
}
public myView(Context context, AttributeSet attrs)
{
this(context,attrs,0);
}
public myView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
paintSet();
}
//android5.0以上使用(API21+)
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public myView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
paintSet();
}
//绘制方法,一切绘制操作都要在里面完成
@Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
//绘制坐标系
canvas.drawPath(drawCoordinateSystem(),paint);
//折线图路径
Path path = new Path();
//添加新点
if(t) {
if(fifth!=null) {
canvas.drawText(fifth, getCoordinateLocation(1), getHeight() - 70, time);
}
if(fourth!=null) {
canvas.drawText(fourth, getCoordinateLocation(0.75), getHeight() - 70, time);
if(third == null) {
path.reset();
pathDetermine(path,true);
drawPoints(canvas,true);
}
}
if(third !=null) {
canvas.drawText(third, getCoordinateLocation(0.5), getHeight() - 70, time);
if(second == null) {
path.reset();
pathDetermine(path,true);
drawPoints(canvas,true);
}
}
if(second!=null) {
canvas.drawText(second, getCoordinateLocation(0.25), getHeight() - 70, time);
if(first == null) {
path.reset();
pathDetermine(path,true);
drawPoints(canvas,true);
}
}
if(first!=null) {
canvas.drawText(first, 40, getHeight() - 70, time);
path.reset();
pathDetermine(path,true);
drawPoints(canvas,true);
}
canvas.drawPath(path,picture);
t = !t;
}
//过渡图像
else if(!t){
if(fifth!=null) {
canvas.drawText(fifth, getCoordinateLocation(0.875), getHeight() - 70, time);
drawPoints(canvas,false);
}
if(fourth!=null) {
canvas.drawText(fourth, getCoordinateLocation(0.625), getHeight() - 70, time);
if(third == null) {
path.reset();
pathDetermine(path,false);
drawPoints(canvas,false);
}
}
if(third !=null) {
canvas.drawText(third, getCoordinateLocation(0.375), getHeight() - 70, time);
if(second == null) {
path.reset();
pathDetermine(path,false);
drawPoints(canvas,false);
}
}
if(second!=null) {
canvas.drawText(second, getCoordinateLocation(0.125), getHeight() - 70, time);
if(first == null) {
path.reset();
pathDetermine(path,false);
drawPoints(canvas,false);
}
}
if(first!=null){
path.reset();
pathDetermine(path,false);
drawPoints(canvas,false);
}
canvas.drawPath(path,picture);
//控制形成图像(添加新点还是过渡)
t = !t;
}
else {
canvas.drawColor(0xFFFFFF);
}
}
//坐标系所显示的数据传递
public void printX(String s){
first = second;
second = third;
third = fourth;
fourth = fifth;
fifth = s;
}
//坐标点数据传递&&确定显示数据的上界下界
public void Point(String s){
one = two;
two = three;
three = four;
four = five;
five = Float.parseFloat(s);
Max = five;
Min = five;
if(four != Float.MIN_VALUE) {
Max = Math.max(Max, four);
Min = Math.min(Min, four);
}
if(three != Float.MIN_VALUE) {
Max = Math.max(Max, three);
Min = Math.min(Min, three);
}
if(two != Float.MIN_VALUE) {
Max = Math.max(Max, two);
Min = Math.min(Min, two);
}
if(one != Float.MIN_VALUE) {
Max = Math.max(Max, one);
Min = Math.min(Min, one);
}
}
//获得坐标点在屏幕上的实际坐标值
private float getTruePoint(float point){
float f = (BOTTOM-TOP)*(point-Min)/(Max-Min)+TOP;
return BOTTOM+TOP-f;
}
//坐标系绘制函数
private Path drawCoordinateSystem(){
Path path = new Path();
path.moveTo(100, 10);
path.lineTo(100, getHeight() - 130);
path.lineTo(getWidth() - 90, getHeight() - 130);
return path;
}
//横坐标具体位置敲定(X轴时间的具体位置)
private float getCoordinateLocation(double location){
float locationX = getWidth()-130-30;
return locationX*(float)location;
}
//横坐标具体位置敲定(折线坐标点的具体位置)
private float getPictureLocation(double location){
float locationX = getWidth()-130-30;
return locationX*(float)location+63;
}
//折线图各点的描绘&&各点数据的描写
private void drawPoints(Canvas canvas,boolean AddNewPoint){
if(AddNewPoint){
if(fifth!=null) {
canvas.drawCircle(getPictureLocation(1), getTruePoint(five),10, point);
canvas.drawText(String.valueOf(five)+"℃", getPictureLocation(1), getTruePoint(five)-10, point);
}
if(fourth!=null) {
canvas.drawCircle(getPictureLocation(0.75), getTruePoint(four),10, point);
canvas.drawText(String.valueOf(four)+"℃", getPictureLocation(0.75), getTruePoint(four)-10, point);
}
if(third!=null) {
canvas.drawCircle(getPictureLocation(0.5), getTruePoint(three),10, point);
canvas.drawText(String.valueOf(three)+"℃", getPictureLocation(0.5), getTruePoint(three)-10, point);
}
if(second!=null) {
canvas.drawPoint(getPictureLocation(0.25), getTruePoint(two), point);
canvas.drawText(String.valueOf(two)+"℃", getPictureLocation(0.25), getTruePoint(two)-10, point);
}
if(first!=null) {
canvas.drawCircle(100, getTruePoint(one),10, point);
canvas.drawText(String.valueOf(one)+"℃", 100, getTruePoint(one)-10, point);
}
}
else{
if(fifth!=null) {
canvas.drawCircle(getPictureLocation(0.875), getTruePoint(five),10, point);
canvas.drawText(String.valueOf(five)+"℃", getPictureLocation(0.875), getTruePoint(five) - 10, point);
}
if(fourth!=null) {
canvas.drawCircle(getPictureLocation(0.625), getTruePoint(four),10, point);
canvas.drawText(String.valueOf(four)+"℃", getPictureLocation(0.625), getTruePoint(four) - 10, point);
}
if(third!=null) {
canvas.drawCircle(getPictureLocation(0.375), getTruePoint(three),10, point);
canvas.drawText(String.valueOf(three)+"℃", getPictureLocation(0.375), getTruePoint(three) - 10, point);
}
if(second!=null) {
canvas.drawCircle(getPictureLocation(0.125), getTruePoint(two),10, point);
canvas.drawText(String.valueOf(two)+"℃", getPictureLocation(0.125), getTruePoint(two) - 10, point);
}
}
}
//折线图路径的确定
private void pathDetermine(Path path,boolean AddNewPoint){
if(AddNewPoint){
if(fifth!=null)
path.moveTo(getPictureLocation(1), getTruePoint(five));
if(fourth!=null)
path.lineTo(getPictureLocation(0.75), getTruePoint(four));
if(third!=null)
path.lineTo(getPictureLocation(0.5), getTruePoint(three));
if(second!=null)
path.lineTo(getPictureLocation(0.25), getTruePoint(two));
if(first!=null)
path.lineTo(100, getTruePoint(one));
}
else {
if(fifth!=null)
path.moveTo(getPictureLocation(0.875), getTruePoint(five));
if(fourth!=null)
path.lineTo(getPictureLocation(0.625), getTruePoint(four));
if(third!=null)
path.lineTo(getPictureLocation(0.375), getTruePoint(three));
if(second!=null)
path.lineTo(getPictureLocation(0.125), getTruePoint(two));
if(first!=null)
path.lineTo(100, (getTruePoint(one)+getTruePoint(two))/2);
}
}
//画笔初始化
private void paintSet(){
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(3);
paint.setTextSize(50);
point = new Paint();
point.setStyle(Paint.Style.FILL);
point.setAntiAlias(true);
point.setStrokeWidth(20);
point.setTextSize(30);
time = new Paint();
time.setStyle(Paint.Style.FILL);
time.setAntiAlias(true);
time.setStrokeWidth(3);
time.setTextSize(50);
picture = new Paint();
picture.setStyle(Paint.Style.STROKE);
picture.setAntiAlias(true);
picture.setStrokeWidth(3);
picture.setTextSize(50);
}
}
/* 调用例子
if(view.t) {
view.printX(string[i]);
view.Point(number[j]);
j++;
i++;
textView.append(String.valueOf(view.one+" "+view.two+" "+view.three+" "+view.four+" "+view.five+" "+"\n"));
textView.append(String.valueOf(view.Max+" "+view.Min)+"\n");
}
view.invalidate();
*/