Android RecyclerLineChart实现图表绘制教程

目录
  • 正文
  • 正常情况下绘制逻辑
    • 左边界绘制
    • 右边界绘制
    • 代码逻辑

正文

本篇介绍线性图标RecyclerLineChart 的绘制,对于图表的公共部分X、Y轴,背景Board等的绘制先前章节已经有过介绍,这里不再重复;以及高亮选中顶部的poupWindow基本的绘制逻辑跟BarChart类似,可参照之前章节。所以针对LineChart,这里只介绍主体图表的绘制逻辑,以及线性表底部的drawFillColor填充。

首先介绍主体图表的逻辑,与BarChart不同之处在于,BartChart的每个Item的绘制比较独立,而LineChart对于当前的Item,需要找到PreItem或者NextItem中的Y的点进行drawLine, 相比而言稍显复杂一些。图表的中间位置的Line还比较容易绘制,图表左右边界是LineChart绘制最难的地方。

整个的绘制逻辑第一章节有介绍在Render类中,这里的话是LineChartRender的drawLineChartWithoutPoint 方法里,这个方法代码比较长,分段介绍:

private <T extends BarEntry> void drawLineChartWithoutPoint(Canvas canvas, RecyclerView parent, YAxis mYAxis) {
  final float parentRightBoard = parent.getWidth() - parent.getPaddingRight();
  final float parentLeft = parent.getPaddingLeft();
  BaseBarChartAdapter adapter = (BaseBarChartAdapter) parent.getAdapter();
  List<T> entryList = adapter.getEntries();
  final int childCount = parent.getChildCount();

  int adapterPosition;
  for (int i = 0; i < childCount; i++) {
    View child = parent.getChildAt(i);
    T barEntry = (T) child.getTag();
    if (barEntry.getY() == 0) {
      continue;
    }
    adapterPosition = parent.getChildAdapterPosition(child);
    RectF rectF = ChartComputeUtil.getBarChartRectF(child, parent,
                                                    mYAxis, mLineChartAttrs, barEntry);
    PointF pointF2 = new PointF((rectF.left + rectF.right) / 2, rectF.top);
          // 这里还有好多绘制逻辑代码
            }//end for
}// end  drawLineChartWithoutPoint

整个绘制绘制依次遍历 Adapter中当前展现的点,总共childcount 个,遍历的当前点位pointF2, 以pointF2 为基准接下来会涉及找 pointF0,pointF1, 这两在pointF2左边(假设存在的情况下);pointF3, pointF4, 这两个点在PointFd2的右边,之所以要找左右各两个点是处理边界情况。

正常情况下绘制逻辑

连接pointF1、pointF2。

if (i < childCount - 1) {//这里的LayoutManager设置的reverse倒叙,所以i+1在i的左边i对应的是pointF2
  View pointF1Child = parent.getChildAt(i + 1);
  T barEntryLeft = (T) pointF1Child.getTag();
  //这里的RectF跟之前的Barchart类似,为ItemView中除去space后所占的RectF区域,其中pointF1的X为RectF的X轴方向的中心。
  RectF rectFLeft = ChartComputeUtil.getBarChartRectF(pointF1Child, parent, mYAxis,   mLineChartAttrs, barEntryLeft);
  //找到PointF1
  PointF pointF1 = new PointF((rectFLeft.left + rectFLeft.right) / 2, rectFLeft.top);
  //parentLeft为左边界, parentRightBoard 为Chart的右边界
  if (pointF1.x >= parentLeft && pointF2.x <= parentRightBoard) {
    float[] pointsOut = new float[]{pointF1.x, pointF1.y, pointF2.x, pointF2.y};
    drawChartLine(canvas, pointsOut);//绘制正常情况下的Line。
    drawFill(parent, mLineChartAttrs, canvas, pointF1, pointF2, rectF.bottom);
    //其它边界绘制逻辑。
}//end if

左边界绘制

以上的情况是pointF1.x 在Chart内,见图, 黄色为当前的PointF1, 紫色为PointF2, 上面代码李drawLine绘制的是PointF1跟PointF2之前的连线。

继续看上面的那个图,要绘制PointF1到Chart左边边界的线段,需要继续找到PointF0,然后用PointF0、PointF1与Chart相交得到上图黑色圈里的点,记为pointFIntercept, drawLine(pointFIntercept, PointF1)

if (pointF1Child.getLeft() < parentLeft) {//左边界,处理pointF1值显示出来了的情况。
  if (adapterPosition + 2 < entryList.size()) {
  float x = pointF1.x - pointF1Child.getWidth();
  T barEntry0 = entryList.get(adapterPosition + 2);
  float y = ChartComputeUtil.getYPosition(barEntry0, parent, mYAxis, mLineChartAttrs);
  PointF pointF0 = new PointF(x, y);
    //PointF0、PointF1 跟Chart的交点pointFIntercept
  PointF pointFIntercept = ChartComputeUtil.getInterceptPointF(pointF0, pointF1, parentLeft);
  float[] points = new float[]{pointFIntercept.x, pointFIntercept.y, pointF1.x, pointF1.y};
  drawChartLine(canvas, points);
  drawFill(parent, mLineChartAttrs, canvas, pointFIntercept, pointF1, rectF.bottom);
   }
}

上面是 pointF1.x >= parentLeft,在左边界内的情况,当pointF1.x < parentLeft时,rectLeft 出来一小部分的情况,如下图所示:紫色为当前的PointF2点

这时需要求PointF1、PointF2跟Chart相交的点pointF, 然后drawLine(pointF, PointF2)即可, 见代码:

if (pointF1.x < parentLeft && pointF1Child.getRight() >= parentLeft) {//左边界,处理pointF1值没有显示出来
  PointF pointF = ChartComputeUtil.getInterceptPointF(pointF1, pointF2, parentLeft);
  float[] points = new float[]{pointF.x, pointF.y, pointF2.x, pointF2.y};
  drawChartLine(canvas, points);
  drawFill(parent, mLineChartAttrs, canvas, pointF, pointF2, rectF.bottom);
}

右边界绘制

处理完左边界的绘制,右边界的绘制跟左边界大致一样,PointF2 往右两个点PointF3, PointF4; 注意这里RecyclerView的LayoutManager为reverse, 所以当 PointF2对应的下标为i时, PointF3对应的为i-1, PointF4为i-2.

然后就是分情况讨论PointF3.x 是否在Chart范围内,跟parentRightBorad比较即可。

看PointF3.x 在 Chart范围内的情况,如图:紫色为PointF2点,黄色为PonitF3点,黑色为PointF3,PointF4跟Chart的交点,这里只需要绘制PointF3跟交点之间的Line;PointF2、PointF3之间的Line 在当黄色点遍历到i时,紫色点位PointF1,所以这里不需要重复绘制了。

代码逻辑

if (pointF3.x < parentRightBoard) {//pointF3 在界内。
  if (adapterPosition - 2 > 0) {
  float xInner = pointF3.x + child.getWidth();
  T barEntry4 = entryList.get(adapterPosition - 2);
  float yInner = ChartComputeUtil.getYPosition(barEntry4, parent, mYAxis, mLineChartAttrs);
  PointF pointF4 = new PointF(xInner, yInner);//找到PointF4.
  PointF pointFInterceptInner = ChartComputeUtil.getInterceptPointF(pointF3, pointF4, parentRightBoard);
  float[] pointsInner = new float[]{pointF3.x, pointF3.y, pointFInterceptInner.x, pointFInterceptInner.y};
  drawChartLine(canvas, pointsInner);
  drawFill(parent, mLineChartAttrs, canvas, pointF3, pointFInterceptInner, rectF.bottom);
  }
}

最后就是 pointF3.x >parentRightBoard的情况,见图:紫色为PointF2, 黄色为 PointF2、PointF3跟Chart的交点:

代码逻辑如下:

if (pointF3.x > parentRightBoard) {//在Chart之外。
  PointF pointFIntercept = ChartComputeUtil.getInterceptPointF(pointF2, pointF3, parentRightBoard);
  float[] points = new float[]{pointF2.x, pointF2.y, pointFIntercept.x, pointFIntercept.y};
  drawChartLine(canvas, points);
  drawFill(parent, mLineChartAttrs, canvas, pointFIntercept, pointF2, rectF.bottom);
}

以上的边界处理中涉及到的工具类方法求相交点,简单的数学公司带入:

public static PointF getInterceptPointF(PointF pointF1, PointF pointF2, float x) {
    float width = Math.abs(pointF1.x - pointF2.x);
    float height = Math.abs(pointF1.y - pointF2.y);
    float interceptWidth = Math.abs(pointF1.x - x);
    float interceptHeight = interceptWidth * 1.0f / width * height;
    float y;
    if (pointF2.y < pointF1.y) {
      y = pointF1.y - interceptHeight;
    } else {
      y = pointF1.y + interceptHeight;
    }
    return new PointF(x, y);
}

见以上图表中的红色半透明的FillColor的绘制,每次drawLine()紧跟着就是drawFill(), 以下是drawFill的逻辑,跟X轴构建一个path,然后drawPath 即可:

private void drawFill(RecyclerView parent, LineChartAttrs mBarChartAttrs, Canvas canvas, PointF pointF, PointF pointF1, float bottom) {
        if (mBarChartAttrs.enableLineFill) {
            float yBottom = parent.getBottom() - parent.getPaddingBottom();
            float yTop = parent.getTop() + parent.getPaddingTop();
            LinearGradient mLinearGradient = new LinearGradient(
                    0,
                    yBottom,
                    0,
                    yTop,
                    new int[]{
                            mBarChartAttrs.lineShaderBeginColor, mBarChartAttrs.lineShaderEndColor},
                    null,
                    Shader.TileMode.CLAMP
            );
            mLineFillPaint.setShader(mLinearGradient);
            Path path = ChartComputeUtil.createColorRectPath(pointF, pointF1, bottom);
            LineChartDrawable drawable = new LineChartDrawable(mLineFillPaint, path);
            drawable.draw(canvas);
        }
    }

设置了一个Color的Linear渐变从bottom到top.

至此,RecyclerLineChart的主体图表绘制逻辑介绍完毕。还有部分的细节,当前Point带圆圈,以及边界圆圈的绘制等,选中圆圈的处理等多处细节,读者想了解的,可以GitHub上下载看源码demo, 连接在本专栏的第一篇里有链接。

以上就是Android RecyclerLineChart实现图表绘制教程的详细内容,更多关于Android RecyclerLineChart图表绘制的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android RecyclerChart其它图表绘制示例详解

    目录 正文 1. 心电图 2. 睡眠图 正文 之前章节介绍了RecyclerChart 中一些通用的图表的相关绘制逻辑,本章节介绍两种Special的Chart的绘制,一种是心电图,一种是睡眠图.首先我们来看下心电图EcgChart的绘制. 1. 心电图 EcgChart 跟LineChart形态上是相似的,但是EcgChart的点相对于LineChart密集的多,之前的LineChart相当于每个RecyclerView的Itemview 中的Model对应的value值,而心电图的ItemD

  • RecyclerBezierChart曲线图表绘制

    目录 曲线图标RecyclerBezierChart 的绘制 三阶贝塞尔曲线 cubicPath 曲线图标RecyclerBezierChart 的绘制 本篇介绍曲线图标RecyclerBezierChart 的绘制, 同样图表的公共部分的绘制这里不再做介绍,主体图表的绘制逻辑在BezierChartRender类中,其中包含主体曲线的绘制以及底部fill部分的渐变色的绘制. 三阶贝塞尔曲线 曲线的绘制用的三阶贝塞尔曲线,关于贝塞尔曲线相关的知识读者可自行Google,Android中的三阶贝塞

  • MPAndroidChart自定义图表Chart的Attribute及Render绘制逻辑

    目录 MPAndroidChart自定义图表 1. 自定义Chart的Attribute 2. Render 自定义绘制逻辑 3. DataBuffer MPAndroidChart自定义图表 声明:本文MPChart 代表的就是 MPAndroidChart. 1. 自定义Chart的Attribute 我们回忆一下自定义View的过程里,通常我们会将一些属性控制Attribute通过自定义View的构造方法传入,然后绘制或者layout的情况下使用这些属性.Attribute类中的属性,通过

  • Android开发X Y轴Board的绘制教程示例

    目录 正文 1. X轴的绘制 2. Y轴的绘制 绘制RightYAxisLabel 3. Board 绘制 正文 上篇大致介绍了RecyclerChart能够绘制的图表,以及一些特有的功能.从这节开始具体地介绍图表的绘制,本节先介绍RcyclerChart中一些图表的相关辅助的绘制,X.Y轴,以及Board的绘制. 上一章节有介绍绘制的逻辑都在ItemDecoration中实现的,而各种图表基本都有X.Y轴.Board相关的绘制,所以把他们的相关逻辑抽象到上层的基类BaseChartItemDe

  • Python可视化绘制图表的教程详解

    目录 1.Matplotlib 程序包 2.绘图命令的基本架构及其属性设置 3.Seaborn 模块介绍 3.1 未加Seaborn 模块的效果 4.描述性统计图形概览 4.1制作数据 4.2 频数分析 python 有许多可视化工具,但本书只介绍Matplotlib.Matplotlib是一种2D的绘图库,它可以支持硬拷贝和跨系统的交互,它可以在python脚本,IPython的交互环境下.Web应用程序中使用.该项目是由John Hunter 于2002年启动,其目的是为python构建MA

  • Android中MPAndroidChart自定义绘制最高点标识的方法

    前言 MPAndroidChart是一款基于Android的开源图表库,MPAndroidChart不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,应用起来非常灵活.MPAndroidChart显得更为轻巧和简单,拥有常用的图表类型:线型图.饼图.柱状图和散点图. MPAndroidChart自定义绘制最高点标识 距离上次发布关于 MPAndroidChart 的文章已经过去一个多月了,项目中新增了一个需求,看起来很简单.就是在最高点绘制矩形框,标识最高点的数值

  • Android开发使用Drawable绘制圆角与圆形图案功能示例

    本文实例讲述了Android开发使用Drawable绘制圆角与圆形图案功能.分享给大家供大家参考,具体如下: 1. 创建类RoundCircleDrawable继承Drawable /** * 圆角矩形 * @Project App_View * @Package com.android.view.drawable * @author chenlin * @version 1.0 * @Date 2016年4月21日 * @Note TODO */ public class RoundCircl

  • Android编程实现canvas绘制柱状统计图功能【自动计算宽高及分度值、可左右滑动】

    本文实例讲述了Android编程实现canvas绘制柱状统计图功能.分享给大家供大家参考,具体如下: 这里实现了一个简单的柱状统计图,如下:   特点: 1.根据数据源自动计算每个条目的高度.宽度.间距,自动计算分度值. 2.当条目数较多时,可左右滑动查看全部内容,图形.文字同步滑动,并且松手后会渐渐的停下来(而不是立刻停下来). 代码: (1)核心代码:BarChartView.Java package com.sina.appbarchart; import android.app.Acti

  • Android开发之OpenGL绘制2D图形的方法分析

    本文实例讲述了Android开发之OpenGL绘制2D图形的方法.分享给大家供大家参考,具体如下: Android为OpenGL ES支持提供了GLSurviceView组建,这个组建用于显示3D图形.GLSurviceView本身并不提供绘制3的图形的功能,而是由GLSurfaceView.Renderer来完成了SurviceView中3D图形的绘制. 归纳起来,在android中使用OpenGL ES需要3个步骤. 1. 创建GLSurviceView组件,使用Activity来显示GLS

  • Android实现给TableLayou绘制边框的方法

    本文实例讲述了Android实现给TableLayou绘制边框的方法.分享给大家供大家参考,具体如下: 效果如下: 思路:使用share作为背景显示边框 步骤: 1.在res/drawable文件夹下建立table_frame_gray.xml文件: <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res

  • Python数据分析:手把手教你用Pandas生成可视化图表的教程

    大家都知道,Matplotlib 是众多 Python 可视化包的鼻祖,也是Python最常用的标准可视化库,其功能非常强大,同时也非常复杂,想要搞明白并非易事.但自从Python进入3.0时代以后,pandas的使用变得更加普及,它的身影经常见于市场分析.爬虫.金融分析以及科学计算中. 作为数据分析工具的集大成者,pandas作者曾说,pandas中的可视化功能比plt更加简便和功能强大.实际上,如果是对图表细节有极高要求,那么建议大家使用matplotlib通过底层图表模块进行编码.当然,我

  • Android MPAndroidChart开源图表库之饼状图的代码

    MPAndroidChart是一款基于Android的开源图表库,MPAndroidChart不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,应用起来非常灵活.MPAndroidChart同样拥有常用的图表类型:线型图.饼图.柱状图和散点图. GitHub地址 下面主要实现以下饼状图: 1.从上面的地址中下载最新mpandroidchartlibrary-2-0-8.jar包, 然后copy到项目的libs中: 2.定义xml文件: 3.主要Java逻辑代码如下

随机推荐