Android中折线图的画法



      折线图的绘制,这种方式可以自定义X轴Y轴的长度,显示的数值的大小,而我之前用的方式根据屏幕的像素来绘制折线图,虽然搞了很久但是一点都不稳定,研究很久才找到这种方法,贴出来和大家分享一

需求:绘制一个折线图,要求一共显示7个点,刚开始的时候没有点,随着数据传入依次显示1,2。。。。7个点,当7个点铺满的时候,新加入的数据占据第一个点的位置,并将第8个点移除屏幕位置。数据为动态加载的。

实现思路:拿一个画笔在画布上画图,首先要定义好一些基础数据,如X轴的最大最小值,显示的点的数量,标题等,具体的看下面的代码部分


public class ChartView extends View {
    public static final int MAX_DATA_COUNT=7;
    private int maxValue=100;
    private int minValue=0;
    private int[]datas=new int[10];
    private int dataCount=0;//
    private String title="";
    private int value;  //传送进来的值,用于判断是否超标
    
    private int viewHeight,viewWidth;
    
    public ChartView(Context context) {
        super(context);    
        for(int i=0;i<MAX_DATA_COUNT;i++)
            datas[i]=20;
    }
    
    public ChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        for(int i=0;i<MAX_DATA_COUNT;i++)
            datas[i]=20; 
    }
    
    public String getTitle() {
        return title;
    }


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


    public int getMaxValue() {
        return maxValue;
    }


    public void setMaxValue(int maxValue) {
        this.maxValue = maxValue;
    }


    public int getMinValue() {
        return minValue;
    }


    public void setMinValue(int minValue) {
        this.minValue = minValue;
    }

/**
 * 传送数据进来
 * @param d    传送进来数据
 * @param value  传送进来的判断数据
 */
    public void addDatas(int d,int value){
        this.value=value;
        if(dataCount<MAX_DATA_COUNT){//datacount作为数组的下标
            datas[dataCount]=d;//如果小于七个点,就一个一个点的加,向右布满七个点
            dataCount++;
            System.out.println("Add Data:"+d);
        }
        else{
            for(int i=0;i<MAX_DATA_COUNT-1;i++){//如果已经有七个点,后一个覆盖前一个,实现点的更新
                datas[i]=datas[i+1];//后一个替换前一个
            }
            datas[MAX_DATA_COUNT-1]=d;
        }
        
        System.out.println("Add Data:"+d);
    }
    
    private float toViewPosX(int x){
        float dx=1.0f*viewWidth/(1.0f*(MAX_DATA_COUNT+2));//得到一个X轴的刻度长度
        return dx+x*dx;        //    第一个刻度加上X*一个刻度,做为当前的X轴的坐标,返回当前X轴的坐标
    }
    private float toViewPosY(int y){
        float dy=1.0f*viewHeight/(1.0f*(maxValue-minValue));//获得一个Y的刻度长度
        return 1.0f*viewHeight-y*dy;//返回当前Y轴的坐标
        
    }
    
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        // TODO Auto-generated method stub
        viewHeight = this.getHeight();
        viewWidth = this.getWidth();
        super.onSizeChanged(w, h, oldw, oldh);
    }
    
    
    @Override
    public void onDraw(Canvas canvas) {//画布
        
        //白色    画笔
        Paint whitePaint = new Paint();
        whitePaint.setAlpha(100);
        whitePaint.setAntiAlias(true);
        whitePaint.setStyle(Paint.Style.FILL);
        whitePaint.setColor(Color.WHITE);
        whitePaint.setStrokeWidth(3);
        
        //红色
        Paint redPaint = new Paint();
        redPaint.setAntiAlias(true);
        redPaint.setAlpha(0);
        redPaint.setStyle(Paint.Style.FILL);
        redPaint.setColor(Color.RED);
        redPaint.setStrokeWidth(3);
        
        //蓝色
        Paint bluePaint = new Paint();
        bluePaint.setAntiAlias(true);
        bluePaint.setAlpha(0);
        bluePaint.setStyle(Paint.Style.FILL);
        bluePaint.setColor(Color.BLUE);
        bluePaint.setStrokeWidth(4);
        
        if(dataCount>0){//如果下标大于0
            //canvas.drawText("dataCount:"+dataCount,10, 50, p);
            
            for (int i = 0; i <dataCount-1; i++) {
                float startX=toViewPosX(i);
                float startY=toViewPosY(datas[i]);            
                float stopX=toViewPosX(i+1);
                float stopY=toViewPosY(datas[i+1]);            
                canvas.drawLine(startX, startY, stopX, stopY, whitePaint);
                if (datas[i]>value) {//当前值大于value,画出前六个点
                    canvas.drawCircle(startX, startY, 5, redPaint);
                    canvas.drawText(String.valueOf(datas[i]), startX-4, startY-6, redPaint);
                }else {
                    canvas.drawCircle(startX, startY, 5, whitePaint);
                    canvas.drawText(String.valueOf(datas[i]), startX-4, startY-6, whitePaint);
                }
                /*canvas.drawText("X"+startX+"Y"+startY, 10, 80, p);
                break;*/
            }
            
            //画最后一个点与值
            if (datas[dataCount-1]>value) {
                canvas.drawCircle(toViewPosX(dataCount-1), toViewPosY(datas[dataCount-1]), 5, redPaint);
                canvas.drawText(String.valueOf(datas[dataCount-1]), toViewPosX(dataCount-1)-4, toViewPosY(datas[dataCount-1])-6, redPaint);
            }else {
                canvas.drawCircle(toViewPosX(dataCount-1), toViewPosY(datas[dataCount-1]), 5, whitePaint);
                canvas.drawText(String.valueOf(datas[dataCount-1]), toViewPosX(dataCount-1)-4, toViewPosY(datas[dataCount-1])-6, whitePaint);
            }
        }
        
        canvas.drawText(title,10, 20, bluePaint);
        canvas.drawText("Max:"+maxValue,10, 40, bluePaint);
        canvas.drawText("Min:"+minValue,10, 60, bluePaint);
    }

    public void reFresh() {
        this.invalidate();
    }
}
附上:将折线图中的点换成图片的方法
//生成一个对象,设定缩放倍数
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize=2;
if(value<342(如果value大于342就把图片设置成另一张图片)){
//获得资源文件drawable中的图片
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pm2_point,options);
//将折线图中的换成图片
canvas.drawBitmap(bitmap, (交点的x轴的坐标)XPoint + i * XScale-3, (交点的Y轴坐标)258-YPoint-YCoord(Data[i]),paint);
       }else if(value>=342(如果value大于342就把图片设置成另一张图片)){
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pm2_point_,options);
canvas.drawBitmap(bitmap, XPoint + i * XScale-3, 258-YPoint-YCoord(Data[i]),paint);
}




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值