android绘制折线图绘制

泡在网上的日子 / 文 发表于2014-10-26 20:59 次阅读 canvas

折线图的实现方法在github上有很多开源的程序,但是对于初学者来讲,简单一点的教程可能更容易入门,下面的文章来自csdn的阳光的小强,或许有用(没仔细阅读,大概看了下文章的结构清晰,折线图的效果也还好)。

转载自阳光的小强的博客http://blog.csdn.net/dawanganban/article/details/31445249


有时候我们在项目中会遇到使用折线图等图形,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); 
        } 
    } 
}


收藏 赞 (59) 踩 (1)
上一篇:从缩略图到原图的zoom效果(方法一)
先来描述一下这种效果,在gridview展示的缩略图界面中,点击任意一张缩略图,会根据缩略图所在的位置慢慢放大与平移图片,最后展示出一张完整的图片,当用户返回的时候动画就反着再播放一次。这种效果的例子可以在“快图应用中可以看到。实际上实现这种效果
下一篇:Android 外部存储权限分析
转自 http://blog.csdn.net/zjbpku/article/details/25161131 本站编辑整理。 不知道你有么有发现,KitKat之后的版本不再支持用户对外置SDcard(Secondary Storage)的写入等操作。如果用户想要将文件等copy到手机中,则只能存储到内部存储器中,而无法存储到