Android简易折线图的实现思路

Android简易折线图的实现方案

万事开头难,不说内容如何,关键在于我终于迈出这一步了!

对于折线图来说,github已经有太多优秀的开源框架,如MPAndroidCharts,使用起来很方便,简单的调用其API方法即可。然在懂得运用的情况下我们更要理解折线图表实现的原理。
最近写了一个简单的折线图,在此分享一下,接下来会逐渐完善与优化,主要就是模仿一些APP已经实现的简易功能。说了那么多的废话,开始行动吧!
说到折线图,我相信大家都不陌生,在很多地方都遇到过如Excel.还有股票走势等等,所以说大家也一定知道折现图长什么样子。那么接下来我们会才想,它是怎么实现的呢??
构思:
折现图的形式:
简而言之,一条X轴,一条Y轴,X轴与Y轴组成区域内的一些点,线,以及这些点、线或坐标轴的文字描述。
猜想:应该怎么实现呢?既然知道了折线图的表现形式,由两条坐标轴,若干点与线组成,那应该就会想到,怎么画坐标轴?怎么画点?怎么画线?怎么把它们给链接起来?

Android简易折线图的实现思路_第1张图片
-13_19h48_51.png

实现步骤

  1. 画坐标轴
  2. 画点
  3. 画线
    Action:
    假如现在有一个2维数组,
protected float[][] points = new float[][]{{1,10}, {2,47}, {3,11}, {4,38}, {5,9},{6,52}, {7,14}, {8,37}, {9,29}, {10,31}};

我们将通过拆线图的形式把每个点绘制出来。
执行自定义View的3个常用方法
OnMeassure OnLayout OnDraw ,在这主要主是OnDraw.

  • 第一步,平移坐标原点:
//平移坐标原点
canvas.translate(50,height-50);
  • 第二步,画X轴及X轴上显示的文本描述:
    注意
    具体怎么画有很多种方法,这里采用的是每次画一小段,一段连接着下一段,最终形成一条完整的线段,
    也可以直接先画一条直线(宽度有限,也可以叫线段,怎么叫无所谓了,实现才是最关键的)。
    当然在画线的时候会画一个点,及关于这个点的描述,具体也可偏移一些以方便显示文本。
private void drawLineXAxis(Canvas canvas) {
    int startX = 0;
    int startY = 0;
    int spaceing = (width-100)/points.length;
    //每次画一小段 也可以直接画一条线,然后再线上绘制具体的各个点,其原理一样,都是等分每次变化一个spaceing
    for (int i = 0;(startX+spaceing*i)
  • 第三步,画Y轴及Y轴上对应显示的文本描述:
    注意
    Y轴相对X轴来说相对稍微复杂一点,因为Y轴上的坐标点刻度不是像X轴一样有什么显示什么,而是显示的一个区间,
    这个区间可以直接用数据源中的最大值最小值表示,也可以通过动态设定。在这里也偷懒了(人为的分成了6份,
    因为可以直观的知道数据的大小,真实应用时应该根据前面所说,用数据源中最大值最小值表示,还是其他设定)。
    这一点我们搞明白了,Y轴也就简单了。同理X轴,要多少个坐标点 就分成多少份,这里也是height/数据长度代表每一区间的高度
    ,绘制Y坐标文本时应该是动态按比例计算,此处直接写6不合理,
    举个例子按照最大最小分6份:
    最小值+(最大值-最小值)/6i //i表示第几段了 或者这么说 起始值 + 段值段数 来表示Y坐标轴点的描述
private void drawLineYAxis(Canvas canvas) {
    int startX = 0;
    int startY = 0;
    int spaceing = (height-100)/points.length;
    //每次画一小段
    for (int i = 0;(startY+spaceing*i)
  • 第四步,画点与点与点连接成的线
    注意 最关键一最后一步了。
    根据数据源,计算出每个点应该在坐标轴上的哪个地方,然后绘制点再连接成线。
    在这里每个点的横坐标简单,同理这也有2各思路,但实质是一样的。
    横坐标是多少 就乘以sapceingWith(X轴分成了多少份),这样就能计算出横坐标点的位置
    纵坐标的话大体相同,因为纵坐标值表示与X不一样,应做一些改进。
spaceingHeightUnit = height/(最大值-最小值)或者height/(终值-起始值)

,这样可以得到每单位的值占有多少像素
然后spaceHeightUnit*Y值(数据源中每条数据的值)
另外就是按比例了 和每单位值多少一样。
代码中直接写了60也是直接写了偷懒原因。可做改进

float pointX = 0;
    float pointY = 0;
    private void drawLinePoints(Canvas canvas) {
        float pointXTemp = 0;
        float pointYTemp = 0;

        for(int i =0;i

主要就是以上4步,画X轴、Y轴、点及点点之间连接形成的线。
这是最终形成的效果图。


Android简易折线图的实现思路_第2张图片
-13_19h48_51.png

当然这只是自己之前第一次写的,测试demo,但最终做成的是这样,
数据全部动态了,代码也优化成更灵活的了,估计后期还可能加上各种事件或者其他效果,慢慢改进吧.

一直阅读别人写的博客,阅读起来感觉很简单,但是自己执行时才发现,代码写起来容易,写这个难啊。
自己头一次 写东西,搞了好久才勉强弄出来了,虽说仍有各种问题,但我终于迈出了这一步!

package com.example.demochart.chart;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import com.example.demochart.util.Tool;

public class SelfLineChartView extends View {

    private int width;// 宽
    private int height;// 高
    private Paint alphaLinePaint;// 半透明画笔
    private Paint linePaint;// 线条画笔
    private Paint textPaint;// 横坐标画笔
    private Paint pointPaint;//点的坐标
    private Paint textEmptyPaint;// 空提示
    private Context context;
    public SelfLineChartView(Context context) {
        super(context);
    }

    public SelfLineChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    private void init() {
        //画笔 X轴
        linePaint = new Paint();
        linePaint.setStyle(Paint.Style.FILL);
        linePaint.setColor(context.getResources().getColor(
                android.R.color.holo_red_dark));
        linePaint.setAntiAlias(true);
        linePaint.setStrokeWidth((float) 2.0);

        //文字画笔
        textPaint = new Paint();
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setColor(context.getResources().getColor(
                android.R.color.holo_red_dark));
        textPaint.setAntiAlias(true);
        textPaint.setTextSize(Tool.dip2px(context, 10));

        //文字画笔
        pointPaint = new Paint();
        pointPaint.setTextAlign(Paint.Align.CENTER);
        pointPaint.setStyle(Paint.Style.FILL);
        pointPaint.setColor(context.getResources().getColor(
                android.R.color.holo_blue_light));
        pointPaint.setAntiAlias(true);
        pointPaint.setTextSize(Tool.dip2px(context, 20));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
        int heightSpec = MeasureSpec.makeMeasureSpec(height,MeasureSpec.EXACTLY);
        setMeasuredDimension(widthSpec, heightSpec);
    }
    protected float[][] points = new float[][]{{1,10}, {2,47}, {3,11}, {4,38}, {5,9},{6,52}, {7,14}, {8,37}, {9,29}, {10,31}};

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //平移坐标原点
        canvas.translate(50,height-50);

        //有多少条数据,把X轴分成多少份,
        drawLineXAxis(canvas);

        drawLineYAxis(canvas);

        drawLinePoints(canvas);
    }
    float pointX = 0;
    float pointY = 0;
    private void drawLinePoints(Canvas canvas) {
        float pointXTemp = 0;
        float pointYTemp = 0;

        for(int i =0;i

接下来 不知道怎么写 了 中断了,也算第一篇文章不管好坏完成了吧。

你可能感兴趣的:(Android简易折线图的实现思路)