• Android自定义组件系列【9】——Canvas绘制折线图


    有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了很多插件,但是很多时候我们需要根据具体项目自定义这些图表,这一篇文章我们一起来看看如何在Android中使用Canvas绘制折线图。先看看绘制的效果:

    实现原理很简单,我就直接给出代码:

    package com.example.testcanvasdraw;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.os.Handler;
    import android.os.Message;
    import android.util.AttributeSet;
    import android.view.View;
    
    public class MyView extends View{
    	private int XPoint = 60;
    	private int YPoint = 260;
    	private int XScale = 8;  //刻度长度
    	private int YScale = 40;
    	private int XLength = 380;
    	private int YLength = 240;
    	
    	private int MaxDataSize = XLength / XScale;
    	
    	private List<Integer> data = new ArrayList<Integer>();
    	
    
    	
    	private String[] YLabel = new String[YLength / YScale];
    	
    	private Handler handler = new Handler(){
    		public void handleMessage(Message msg) {
    			if(msg.what == 0x1234){
    				MyView.this.invalidate();
    			}
    		};
    	};
    	public MyView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		for(int i=0; i<YLabel.length; i++){
    			YLabel[i] = (i + 1) + "M/s";
    		}
    		
    		new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				while(true){
    					try {
    						Thread.sleep(1000);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					if(data.size() >= MaxDataSize){
    						data.remove(0);
    					}
    					data.add(new Random().nextInt(4) + 1);
    					handler.sendEmptyMessage(0x1234);
    				}
    			}
    		}).start();
    	}
    	
    	@Override
    	protected void onDraw(Canvas canvas) {
    		super.onDraw(canvas);
    		Paint paint = new Paint();
    		paint.setStyle(Paint.Style.STROKE);
    		paint.setAntiAlias(true); //去锯齿
    		paint.setColor(Color.BLUE);
    		
    		//画Y轴
    		canvas.drawLine(XPoint, YPoint - YLength, XPoint, YPoint, paint);
    		
    		//Y轴箭头
    		canvas.drawLine(XPoint, YPoint - YLength, XPoint - 3, YPoint-YLength + 6, paint);  //箭头
    	    canvas.drawLine(XPoint, YPoint - YLength, XPoint + 3, YPoint-YLength + 6 ,paint);
    	    
    	    //添加刻度和文字
    	    for(int i=0; i * YScale < YLength; i++) {
    	    	canvas.drawLine(XPoint, YPoint - i * YScale, XPoint + 5, YPoint - i * YScale, paint);  //刻度
    	    	
    	    	canvas.drawText(YLabel[i], XPoint - 50, YPoint - i * YScale, paint);//文字
    	    }
    		
    		//画X轴
    		canvas.drawLine(XPoint, YPoint, XPoint + XLength, YPoint, paint);
    		System.out.println("Data.size = " + data.size());
    		if(data.size() > 1){
    			for(int i=1; i<data.size(); i++){
    			    canvas.drawLine(XPoint + (i-1) * XScale, YPoint - data.get(i-1) * YScale, 
    			    		XPoint + i * XScale, YPoint - data.get(i) * YScale, paint);
    			}
    		}
    	}
    }
    
    上面绘制折线部分我们还有一种方式同样可以实现:

    		if(data.size() > 1){
    			Path path = new Path();
    			path.moveTo(XPoint, YPoint - data.get(0) * YScale);
    			for(int i=1; i<data.size(); i++){
    				path.lineTo(XPoint + i * XScale, YPoint - data.get(i) * YScale);
    			}
    			canvas.drawPath(path, paint);
    		}
    下面我们将上面代码修改,让折线下面的区域颜色填充

    package com.example.testcanvasdraw;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.os.Handler;
    import android.os.Message;
    import android.util.AttributeSet;
    import android.view.View;
    /**
     * 
     * @author 阳光小强
     * http://blog.csdn.net/dawanganban
     *
     */
    public class MyView extends View {
    	private int XPoint = 60;
    	private int YPoint = 260;
    	private int XScale = 8; // 刻度长度
    	private int YScale = 40;
    	private int XLength = 380;
    	private int YLength = 240;
    
    	private int MaxDataSize = XLength / XScale;
    
    	private List<Integer> data = new ArrayList<Integer>();
    
    	private String[] YLabel = new String[YLength / YScale];
    
    	private Handler handler = new Handler() {
    		public void handleMessage(Message msg) {
    			if (msg.what == 0x1234) {
    				MyView.this.invalidate();
    			}
    		};
    	};
    
    	public MyView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		for (int i = 0; i < YLabel.length; i++) {
    			YLabel[i] = (i + 1) + "M/s";
    		}
    
    		new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				while (true) {
    					try {
    						Thread.sleep(1000);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					if (data.size() >= MaxDataSize) {
    						data.remove(0);
    					}
    					data.add(new Random().nextInt(4) + 1);
    					handler.sendEmptyMessage(0x1234);
    				}
    			}
    		}).start();
    	}
    
    	@Override
    	protected void onDraw(Canvas canvas) {
    		super.onDraw(canvas);
    		Paint paint = new Paint();
    		paint.setStyle(Paint.Style.STROKE);
    		paint.setAntiAlias(true); // 去锯齿
    		paint.setColor(Color.BLUE);
    
    		// 画Y轴
    		canvas.drawLine(XPoint, YPoint - YLength, XPoint, YPoint, paint);
    
    		// Y轴箭头
    		canvas.drawLine(XPoint, YPoint - YLength, XPoint - 3, YPoint - YLength
    				+ 6, paint); // 箭头
    		canvas.drawLine(XPoint, YPoint - YLength, XPoint + 3, YPoint - YLength
    				+ 6, paint);
    
    		// 添加刻度和文字
    		for (int i = 0; i * YScale < YLength; i++) {
    			canvas.drawLine(XPoint, YPoint - i * YScale, XPoint + 5, YPoint - i
    					* YScale, paint); // 刻度
    
    			canvas.drawText(YLabel[i], XPoint - 50, YPoint - i * YScale, paint);// 文字
    		}
    
    		// 画X轴
    		canvas.drawLine(XPoint, YPoint, XPoint + XLength, YPoint, paint);
    
    		// 绘折线
    		/*
    		 * if(data.size() > 1){ for(int i=1; i<data.size(); i++){
    		 * canvas.drawLine(XPoint + (i-1) * XScale, YPoint - data.get(i-1) *
    		 * YScale, XPoint + i * XScale, YPoint - data.get(i) * YScale, paint); }
    		 * }
    		 */
    		paint.setStyle(Paint.Style.FILL);
    		if (data.size() > 1) {
    			Path path = new Path();
    			path.moveTo(XPoint, YPoint);
    			for (int i = 0; i < data.size(); i++) {
    				path.lineTo(XPoint + i * XScale, YPoint - data.get(i) * YScale);
    			}
    			path.lineTo(XPoint + (data.size() - 1) * XScale, YPoint);
    			canvas.drawPath(path, paint);
    		}
    	}
    }

    上面的效果有时候还是达不到我们的要求,我们将代码修改后效果如下:

    package com.example.testcanvasdraw;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.os.Handler;
    import android.os.Message;
    import android.util.AttributeSet;
    import android.view.View;
    
    /**
     * 
     * @author 阳光小强 http://blog.csdn.net/dawanganban
     * 
     */
    public class MyView extends View {
    	private int XPoint = 60;
    	private int YPoint = 260;
    	private int XScale = 8; // 刻度长度
    	private int YScale = 40;
    	private int XLength = 380;
    	private int YLength = 240;
    
    	private int MaxDataSize = XLength / XScale;
    
    	private List<Integer> data = new ArrayList<Integer>();
    
    	private String[] YLabel = new String[YLength / YScale];
    
    	private Handler handler = new Handler() {
    		public void handleMessage(Message msg) {
    			if (msg.what == 0x1234) {
    				MyView.this.invalidate();
    			}
    		};
    	};
    
    	public MyView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		for (int i = 0; i < YLabel.length; i++) {
    			YLabel[i] = (i + 1) + "M/s";
    		}
    
    		new Thread(new Runnable() {
    
    			@Override
    			public void run() {
    				while (true) {
    					try {
    						Thread.sleep(1000);
    					} catch (InterruptedException e) {
    						e.printStackTrace();
    					}
    					if (data.size() >= MaxDataSize) {
    						data.remove(0);
    					}
    					data.add(new Random().nextInt(4) + 1);
    					handler.sendEmptyMessage(0x1234);
    				}
    			}
    		}).start();
    	}
    
    	@Override
    	protected void onDraw(Canvas canvas) {
    		super.onDraw(canvas);
    		Paint paint = new Paint();
    		paint.setStyle(Paint.Style.STROKE);
    		paint.setAntiAlias(true); // 去锯齿
    		paint.setColor(Color.BLUE);
    
    		// 画Y轴
    		canvas.drawLine(XPoint, YPoint - YLength, XPoint, YPoint, paint);
    
    		// Y轴箭头
    		canvas.drawLine(XPoint, YPoint - YLength, XPoint - 3, YPoint - YLength
    				+ 6, paint); // 箭头
    		canvas.drawLine(XPoint, YPoint - YLength, XPoint + 3, YPoint - YLength
    				+ 6, paint);
    
    		// 添加刻度和文字
    		for (int i = 0; i * YScale < YLength; i++) {
    			canvas.drawLine(XPoint, YPoint - i * YScale, XPoint + 5, YPoint - i
    					* YScale, paint); // 刻度
    
    			canvas.drawText(YLabel[i], XPoint - 50, YPoint - i * YScale, paint);// 文字
    		}
    
    		// 画X轴
    		canvas.drawLine(XPoint, YPoint, XPoint + XLength, YPoint, paint);
    
    		// 绘折线
    		/*
    		 * if(data.size() > 1){ for(int i=1; i<data.size(); i++){
    		 * canvas.drawLine(XPoint + (i-1) * XScale, YPoint - data.get(i-1) *
    		 * YScale, XPoint + i * XScale, YPoint - data.get(i) * YScale, paint); }
    		 * }
    		 */
    		paint.setColor(Color.RED);
    		paint.setStrokeWidth(5);
    
    		Paint paint2 = new Paint();
    		paint2.setColor(Color.BLUE);
    		paint2.setStyle(Paint.Style.FILL);
    		if (data.size() > 1) {
    			Path path = new Path();
    			Path path2 = new Path();
    			path.moveTo(XPoint, YPoint - data.get(0) * YScale);
    			path2.moveTo(XPoint, YPoint);
    			for (int i = 0; i < data.size(); i++) {
    				path.lineTo(XPoint + i * XScale, YPoint - data.get(i) * YScale);
    				path2.lineTo(XPoint + i * XScale, YPoint - data.get(i) * YScale);
    			}
    			path2.lineTo(XPoint + (data.size() - 1) * XScale, YPoint);
    			canvas.drawPath(path, paint);
    			canvas.drawPath(path2, paint2);
    		}
    	}
    }

    感谢你对“阳光小强"的关注,我的另一篇博文很荣幸参加了CSDN举办的博文大赛,如果你觉的小强的博文对你有帮助,请为小强投上你宝贵的一票,投票地址http://vote.blog.csdn.net/Article/Details?articleid=30101091


  • 相关阅读:
    Beans
    Redis记录-Redis命令
    Redis记录-Redis介绍
    RESTful记录-RESTful服务
    RESTful记录-RESTful内容
    RESTful记录-RESTful介绍
    HTTP记录-HTTP介绍
    Solr记录-solr检索和查询数据
    Solr记录-solr文档xml
    Solr记录-solr内核与索引
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468896.html
Copyright © 2020-2023  润新知