Android自定义控件之《折线图的绘制》

金融软件里的行情分时图,这是我们最常见的折线图,当然了,折线图的用途并不仅仅局限于此,像一般在一定区间内,为了更好的能显示出幅度的变化,那么用折线图来展示无疑是最符合效果的,当然了,网上也有很多的第三方开源,这篇文章呢,对开源的不做过多描述,想要了解请关注后续文章,好了,废话不多说,让我们从0来一步步绘制折线图吧。


先来看一下我们最终要实现的效果:

        



很简单的一个空气质量折线图,俗话说,磨刀不误砍柴功,我们可以简单的分析一下,这个折线图主要包含了那几块,上面的标题可以做为一块,xy坐标轴是一块,折线是一块,简单的分为三块之后,代码我们就可以一块一块的去写。


定义一个类继承于View,实现其构造方法,先初始化我们需要的东西,背景设置偏黑色,初始化画笔。


private void initView() {
    setBackgroundColor(Color.parseColor("#222222"));
    
mPaint new Paint();
}


在onDraw()方法里绘制标题:


/**
 * 
绘制标题
 */
private void canvasTitle(Canvas canvas) {
    mPaint.setColor(Color.WHITE);
    
mPaint.setTextSize(50);
    
mPaint.setTypeface(blodFont);
    
canvas.drawText("帝都空气质量趋势图(author:AbnerMing)"10050mPaint);
}


setTypeface()是用来设置字体,这里我设置的是,宋体加粗

Typeface blodFont = Typeface.create("宋体"Typeface.BOLD);


在onDraw()方法里绘制XY轴:

为了使整体看起来稍稍美观,我们绘制的时候,尽量与上下左右保持一定的距离,这里我设置的是距离底部为this.getBottom()-100,距离左边为100,代码如下:


int marginBottom = this.getBottom() - 100;
int 
marginLeft = 100;


初始化XY轴:


//初始化X
mPaint.setColor(Color.WHITE);
canvas.drawLine(marginLeftmarginLeftmarginLeftmarginBottommPaint);
//初始化Y
mPaint.setStrokeWidth(6);
canvas.drawLine(marginLeftmarginBottom, this.getRight() - 20marginBottommPaint);


XY轴绘制好之后,紧接着我们绘制时间轴,时间轴,这里我分成了5份,每份为5个小时,最后一份为4个小时,一份的宽度计算方式为:屏幕的宽度-距离右边的宽度-距离左边的宽度/5,代码如下:


int xWidth = (this.getRight() - 20 - marginLeft) / 5;


起始位置呢,就是距离左边的距离:


int xLine = marginLeft;//起始位置


每一个时间点,都是逐个增加一份的宽度,这里我们new一个Integer数组来存储:


Integer[] xPoint = new Integer[5];
for 
(int a = 0a < 5a++) {
    xLine += xWidth;
    
xPoint[a] = xLine;
}


xPoint就是各个时间点的X轴坐标,显然Y轴是不变的,那么我们就可以如下绘制;


for (int i = 0i < xPoint.lengthi++) {
    mPaint.setColor(Color.parseColor("#FF00FF"));
    
mPaint.setTextSize(40);
    
mPaint.setTypeface(font);
    
mPaint.setTextAlign(Paint.Align.RIGHT);
    if 
(i == 0) {
        canvas.drawText("0"marginLeft,
                
marginBottom + 50mPaint);
        
canvas.drawText(times[i]xPoint[i],
                
marginBottom + 50mPaint);
    
else {
        canvas.drawText(times[i]xPoint[i],
                
marginBottom + 50mPaint);

    
}
}


times是自己定义的时间数组:


private String[] times = {"5:00""10:00""15:00""20:00""24:00"};


X轴的时间绘制好后,接着我们来绘制Y轴,其实Y轴的思路和X轴一样,也是分成5份,每份的计算方式为:屏幕的高度-距离底部的距离-距离上部的距离/5,代码如下;


int yHeight = (marginBottom - marginLeft) / 5;


由于5份每份的颜色值不一样,所以我们要逐一进行处理:


for (int i = 0i < xPoint.lengthi++) {
    mPaint.setStrokeWidth(6);
    int 
startY = marginBottom - yHeight * (i + 1);
    int 
endY = marginBottom - yHeight * i;
    switch 
(i) {
        case 0:
            mPaint.setColor(Color.GREEN);
            break;
        case 
1:
            mPaint.setColor(Color.YELLOW);
            break;
        case 
2:
            mPaint.setColor(0xFFFF7E00);
            break;
        case 
3:
            mPaint.setColor(Color.RED);
            break;
        case 
4:
            mPaint.setColor(0xFF8E1752);
            break;
    
}
    //绘制颜色线
    
canvas.drawLine(marginLeftstartY,
            
marginLeftendYmPaint);
    
//绘制空气污染值
    
canvas.drawText(atmosphereNum[i] + ""marginLeft - 20,
            
startYmPaint);
    
//绘制空气污染等级
    
canvas.drawText(atmosphere[i]marginLeft - 20,
            
endY - yHeight / 2mPaint);
}


atmosphere是自己定义的污染值等级数组,atmosphere是自己定义的污染值数组:


private String[] atmosphere = {""""""""""};
private int[] atmosphereNum = {100200300400500};


再来看最后一块,折线图的绘制。其实每个点就是一个坐标,绘制之前我们先把需要的数据整理一下:


private float[] broken = {0f30f75f160f66f170f80f120f,130f,150f,138f,180f,200f,
        
220f,300f,235f,245f,260f,210f,270f,290f,270f,270f,250f,210f,180f,260f,280f,320f};
private int
[] brokenTimes = {05101520253035,40,45,50,55,60,
        
65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140};
private 
Paint mPaint;


broken数组,是空气污染值,下面的brokenTimes是时间点,我是这样做的,X轴是24小时,共有1440分钟,我分成了10分钟一个点,也就是最多有144个点,brokenTimes里的数值都是增的,毕竟时间走着走着不可能变小,broken数组和brokenTimes数组的长度一定要一样大,因为,各个对应的值就是xy值。

纵轴是500个值,所以纵轴刻度值等于屏幕的高度-距离底部的距离-距离上部的距离/500,代码如下:


float brokenSizeY = (marginBottom - marginLeft) / 500;//得到纵轴刻度值


横轴刻度值等于屏幕的宽度-距离左边的距离-距离右边的距离/144,代码如下:


float brokenSizeX = (this.getRight() - 20 - marginLeft) / 144;


绘制如下:


float lastX = brokenTimes[0] * brokenSizeX + marginLeftlastY = marginBottom - broken[0] * brokenSizeY;
for 
(int a = 0a < broken.lengtha++) {
    float height = marginBottom - broken[a] * brokenSizeY;
    float 
width = brokenTimes[a] * brokenSizeX + marginLeft;
    
canvas.drawCircle(widthheight10mPaint);

    
canvas.drawLine(lastXlastYwidthheightmPaint);
    
lastX = width;
    
lastY = height;
}


lastX是记录上一个X点,lastY是记录上一个Y点。


经过以上的代码,我们就可以绘制出文章刚开始的图片效果了,具体使用,也特别简单,哪里需要用,就在layout里调用就可以了:

<com.ming.abner.chartline.BrokenLineView
    android:layout_width="match_parent"
    
android:layout_height="match_parent"
    
/>


详细代码可关注我的微信公众账号HelloAbner(或扫描评论第一条二维码关注),回复“自定义折线图”,完整的类就会发送给您。



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员一鸣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值