实现原理:
首先这个DataView继承View,重写Draw方法,这样当界面展现出来的时候会调用我们自己写的方法,绘制自己想要的图像。
因为这个DataView只负责绘制List集合里面的所有数据,所以外界需要向Dataview里面的list传值,所以我就定义了静态的List变量,方便外界调用。现在我们可以向DataView里面传入数据了,但是如何实时的去动态刷新呢?
这里需要一个handler,方便检测是否需要更新UI,如果需要更新UI的话,外界就可以向handler发送消息,提示该更新UI,这里需要调用invalidate(),他会调用我们的onDraw方法。这里我已经在初始化类的时候,将当前的引用交给了自己的一个静态变量,所以外界可以去直接调用handlder。你也可以使用单列设计。
每次刺激handler都会调用onDraw一次,都会重新读取list集合里面的数据然后重新绘制,所以你就会看见动态的折线图效果。
参考代码:自己根据需求进行修改
package com.myfirstapp;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AlertDialog;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Created by Lachie on 2017/3/12.
*/
public class DataView extends View {
private int screenWidth;
private int screenHeight;
private Canvas canvas;
private Paint paint;
public static DataView dataView = null;
public static final List<Integer> datas = new ArrayList<Integer>();
private Button close = null;
private int xNum = 50;
public DataView(Context context, AttributeSet attrs) {
super(context, attrs);
dataView = this;
close = (Button) findViewById(R.id.dd_close_btn);
}
public Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(datas.size() == 30){//永远保持固定数据
datas.remove(0);
}
DataView.this.invalidate();//重新draw
xNum = 50;//重置x轴
}
};
//每次放入数据都会绘制,
@Override
protected void onDraw(Canvas canvas) {
Log.d("t","==============================");
this.canvas = canvas;//方便后续调用
screenHeight = getHeight();
screenWidth = getWidth();
int value = 500;
Log.d("t",screenHeight+"");
Log.d("t",screenWidth+"");
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
paint.setFakeBoldText(true);
this.paint = paint;//后续用
//Y轴
canvas.drawLine(50,50,50,screenHeight-50,paint);
//Y轴箭头
canvas.drawLine(50,50,30,80,paint);
canvas.drawLine(50,50,80,80,paint);
//X轴 (x,y) - > (x,y)
canvas.drawLine(50,screenHeight-50,screenWidth-50,screenHeight-50,paint);
//X轴箭头
canvas.drawLine(screenWidth-50,screenHeight-50,screenHeight-80,screenHeight-80,paint);
canvas.drawLine(screenWidth-50,screenHeight-50,screenHeight-80,screenHeight-50+30,paint);
//实际的1/5 值
int block = value /5;
//模拟的1/5 值
int vBlock = screenHeight /5;
Log.d("t","单位长度:" +vBlock);//单位长度
//画Y刻度
//没走一个单位长度 描绘一个刻度
//开始的位置i为y最高点 ; 只要小于50就停止绘制; i每次都会减少一个单位长度
for(int i= screenHeight - 50,count = 0; i> 50; i-=vBlock,count++){
Log.d("t","绘制:" +i);
//x开始 :50 , x结束:向右加10 ; y开始:y的最低点 + 单位长度 , y结束:不变 |
// 可以想象成 y在向下慢慢移动,而x只是小范围的向左移动,而且每次y下降的时候都是向右移动一下
canvas.drawLine(50,i,50 + 10,i,paint);
//在(0,i)的位置写字
Log.d("t","单位" + count *block + "");
canvas.drawText(count *block +"",10,i,paint);
}
//如果datas里有数据就绘图
Log.d("t","数据大小:" + datas.size());
/*
*
* 每隔一秒存放一个数据,然后重新画UI
*
* 当存放了2个数据的时候就开始画UI
* list集合的第一位画到list集合的第一位 + 1 这样就是一条线了,当划到最后一条线的时候(也就是集合的大小 - 1 的时候,说明是最后一条线)就不画了。
*
* */
if(datas.size() >= 2){
for(int i=0; i<datas.size(); i++){
if(i != datas.size() - 1){
Log.d("t",datas.get(i)+"");
//传进来的是整数,y轴和现实中相反,所以我需要进行转换 还有比列问题
int y = (int)(screenHeight -50 - (datas.get(i)*1.7)) ;
int vY = (int)(screenHeight -50 - (datas.get(i+1)*1.7)) ;
Log.d("t",y + ", " + vY);
Log.d("t",screenHeight -50 + "," + (screenHeight -50));
canvas.drawLine(xNum,y,xNum+=20,vY,paint);
}
}
}
}
}