Android开发自定义控件之折线图实现方法详解

本文实例讲述了Android开发自定义控件之折线图实现方法。分享给大家供大家参考,具体如下:

前言

折线图是Android开发中经常会碰到的效果,但由于涉及自定义View的知识,对许多刚入门的小白来说会觉得很高深。其实不然,接下来我就以尽量通俗的语言来说明下图折线图效果的实现过程。

效果图

实现过程

首先,选择自定义控件的方式。

自定义控件的实现有四种方式:

1.继承View,重写onDraw、onMeasure等方法。
2.继承已有的View(比如TextView)。
3.继承ViewGroup实现自定义布局。
4.继承已有的ViewGroup(比如LinearLayout)。

由于我们不需要多个控件进行组合,也不需要在原有控件基础上改造,故我们采用第1种方式即继承View来实现。代码如下,新建一个ChartView类继承自View,并实现他的几个构造方法,并重写onDraw和onMeasure方法,因为我们要在onDraw方法里面进行绘制工作,并且我希望这个控件的长宽是相等的,所以在onMeasure方法设置宽高相等。设置长宽相等的方式很简单,我们不需要自己去测量实现,只需要调用父类的onMeasure方法,传参数(宽高值)时将都传入宽度(或者高度)即可。

public class ChartView extends View {

  public ChartView(Context context) {
    super(context);
  }

  public ChartView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
  }

  public ChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
  }
}

其次,绘制简单图形并显示出来。

在进行绘制之前,我们要进行若干初始化工作,其中就包括画笔的初始化。然后就可以进行绘制了,我们先绘制一个简单的圆圈,然后将控件放到布局文件中,运行看看效果。

ChartView代码

public class ChartView extends View {

  // 画笔
  private Paint paint;

  /**
  * 构造函数
  */
  public ChartView(Context context) {
    super(context);
    initWork();
  }

  /**
  * 构造函数
  */
  public ChartView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    initWork();
  }

  /**
  * 构造函数
  */
  public ChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initWork();
  }

  /**
  * 初始化工作
  */
  private void initWork() {
    initPaint();
  }

  /**
  * 画笔设置
  */
  private void initPaint() {
    paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    // 画笔样式为填充
    paint.setStyle(Paint.Style.FILL);
    // 颜色设为红色
    paint.setColor(Color.RED);
    // 宽度为3像素
    paint.setStrokeWidth(3);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 画圆
    canvas.drawCircle(300,300,100,paint);
  }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"

  <com.toprs.linechart.ChartView
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</android.support.constraint.ConstraintLayout>

效果:

然后,绘制图表。

到目前为止,已经实现了最简单的一个自定义控件,虽然它什么功能都没有,只是简单显示一个红色圆圈,但本质都是一样的。接下来就开始图表的绘制。

1.初始化一些需要使用的值。

  // 刻度之间的距离
  private int degreeSpace;
  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 控件上下左右边界四至及控件的宽度(同时也是高度!)
    int left = getLeft();
    int right = getRight();
    int top = getTop();
    int bottom = getBottom();
    int w = getWidth();

    // 图表距离控件边缘的距离
    int graphPadding = w / 10;
    // 图表上下左右四至
    int graphLeft = left + graphPadding;
    int graphBottom = bottom - graphPadding;
    int graphRight = right - graphPadding;
    int graphTop = top + graphPadding;
    // 图表宽度(也等同高度奥~)
    int graphW = graphRight - graphLeft;
    // 刻度之间的距离
    degreeSpace = graphW / 8;
  }

2.灰色背景

  // 背景
  canvas.drawColor(Color.LTGRAY);

3.坐标系

  // 画笔设置样式为STROKE样式,即只划线不填充
  paint.setStyle(Paint.Style.STROKE);

  // 坐标系绘制
  Path pivotPath = new Path();
  //Y轴
  pivotPath.moveTo(graphLeft, graphBottom);
  pivotPath.lineTo(graphLeft, graphTop);
  //Y轴箭头
  pivotPath.lineTo(graphLeft - 12, graphTop + 20);
  pivotPath.moveTo(graphLeft, graphTop);
  pivotPath.lineTo(graphLeft + 12, graphTop + 20);
  //X轴
  pivotPath.moveTo(graphLeft, graphBottom);
  pivotPath.lineTo(graphRight, graphBottom);
  //X轴箭头
  pivotPath.lineTo(graphRight - 20, graphBottom + 12);
  pivotPath.moveTo(graphRight, graphBottom);
  pivotPath.lineTo(graphRight - 20, graphBottom - 12);
  canvas.drawPath(pivotPath, paint);

4.刻度虚线及数字

  // Y轴刻度虚线
  for (int i = 1; i < 8; i++) {
    Path yKeduPath = new Path();
    // 线
    paint.setColor(Color.WHITE);
    paint.setStrokeWidth(1);
    paint.setStyle(Paint.Style.STROKE);
    paint.setPathEffect(new DashPathEffect(new float[]{5,5},0));
    yKeduPath.moveTo(graphLeft, graphBottom - i * degreeSpace);
    yKeduPath.lineTo(graphRight, graphBottom - i * degreeSpace);
    canvas.drawPath(yKeduPath, paint);
    // 数字
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.FILL);
    paint.setTextSize(25);
    paint.setPathEffect(null);
    canvas.drawText(i + "", graphPadding / 2, graphBottom - i * degreeSpace, paint);
  }
  // X轴刻度虚线
  for (int i = 1; i < 8; i++) {
    Path xKeduPath = new Path();
    // 线
    paint.setColor(Color.WHITE);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(1);
    paint.setPathEffect(new DashPathEffect(new float[]{5,5},0));
    xKeduPath.moveTo(graphLeft + i * degreeSpace, graphBottom);
    xKeduPath.lineTo(graphLeft + i * degreeSpace, graphTop);
    canvas.drawPath(xKeduPath, paint);
    // 数字
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.FILL);
    paint.setTextSize(25);
    paint.setPathEffect(null);
    canvas.drawText(i + "", graphLeft + i * degreeSpace, graphBottom + graphPadding / 2, paint);
  }

5.折线

在绘制折线之前,我们先要初始化几个参数。

  // 模拟数据
  private float[] data = {3.2f, 4.3f, 2.5f, 3.2f, 3.8f, 7.1f, 1.3f, 5.6f};
  // 当前显示的数据数量
  private int showNum=1;
  // 折线
  Path linePath = new Path();
  for (int i = 0; i < showNum; i++) {
    int toPointX = graphLeft + i * degreeSpace;
    int toPointY = graphBottom - ((int) (data[i] * degreeSpace));
    paint.setColor(Color.YELLOW);
    paint.setStyle(Paint.Style.STROKE);
    if (i==0){
      linePath.moveTo(toPointX,toPointY);
    }else {
      linePath.lineTo(toPointX, toPointY);
    }
    // 节点圆圈
    canvas.drawCircle(toPointX, toPointY,10,paint);
    paint.setColor(Color.WHITE);
    paint.setStyle(Paint.Style.FILL);
    canvas.drawCircle(toPointX,toPointY,7,paint);
  }
  paint.setColor(Color.YELLOW);
  paint.setStyle(Paint.Style.STROKE);
  paint.setStrokeWidth(3);
  canvas.drawPath(linePath, paint);

6.让图表动起来

为了实现数据依次显现的动画,我们开启一个线程是当前显示的数据数量即showNum变量不断加一,并间隔时间0.5秒。然后postInvalidate()重绘即可。

  private void initWork() {
    initPaint();
    // 开启线程,没隔0.5秒showNum加一
    new Thread(new Runnable() {
      @Override
      public void run() {
        while (true){
          if (showNum<data.length){
            showNum++;
          }else {
            showNum=1;
          }
          // 重绘
          postInvalidate();
          // 休眠0.5秒
          try {
            Thread.sleep(500);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }).start();
  }

好了,运行一下,便会实现上面的效果了。如果你觉得效果不够炫酷或者功能太少,那就自己完善吧~~

结语

由于自定义控件是Android进阶路上必然要碰到的知识,所以希望大家重视。其实自定义控件说难也难说简单也简单。实现一些普通的效果还是很方便的,像这次举的例子,但如果要实现各种炫酷效果并且要完善各种功能的话,就需要各种知识的配合了,包括数学、物理、绘图等知识。所以还是需要平时不断积累的,看到别人的控件很棒的时候自己可以试着去实现一下,对自己的知识库不断进行补充,自然会娴熟的运用。本人也是菜鸟一枚,望共勉!!

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android控件用法总结》、《Android开发入门与进阶教程》、《Android视图View技巧总结》、《Android编程之activity操作技巧总结》、《Android数据库操作技巧总结》及《Android资源操作技巧汇总》

希望本文所述对大家Android程序设计有所帮助。

(0)

相关推荐

  • MPAndroidChart开源图表库的使用介绍之饼状图、折线图和柱状图

    MPAndroidChart开源图表库之饼状图 为大家介绍一款图标开源库MPAndroidChart,它不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,用起来非常灵活.MPAndroidChart同样拥有常用的图表类型:线型图.饼图.柱状图和散点图. mpandroidchartlibrary.jar包下载地址: https://github.com/PhilJay/MPAndroidChart/releases 下面主要实现以下饼状图: 1.从上面的地址中下载

  • 详解Android图表 MPAndroidChart折线图

    1.介绍 MPAndroidChart GitHub地址 MPAndroidChart的强大之处就不在多说了,目前最新的版本是3.0.1,在新版本中很多方法都被弃用了,这个要注意一下,在网上查到的大多数资料都是关于旧版本的,今天来实现一下折线图,把过程记录下来,分享给大家. 效果图: 2.引入开源库 在项目根目录的build.gradle文件中加入如下代码 allprojects { repositories { maven { url "https://jitpack.io" } }

  • Android HelloChart开源库图表之折线图的实例代码

    前面我们介绍了开源图表库MPAndroidChart,请参考: Android MPAndroidChart开源库图表之折线图的实例代码 我们今天介绍的将是一个更为优秀的图表库,比MPAndroidChart性能更好,功能更完善,UI风格更美观,坐标轴更精细. 支持缩放.滑动以及平移.Zoom(pinch to zoom, double tap zoom), scroll and fling 支持自定义坐标轴(比如坐标轴位置:上下左右内部),支持自动生成坐标轴.Custom and auto-g

  • Android自定义View实现折线图效果

    下面就是结果图(每种状态用一个表情图片表示): 一.主页面的布局文件如下: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height=&quo

  • Android开发之天气趋势折线图

    先来看下效果: 控件内容比较简单,就是一个普通的折线图,上下分别带有数字,点击的时候显示当天温度的差值. 创建一个类继承自View,并添加两个构造方法: public class TrendGraph extends View { public TrendGraph(Context context) { // 在java代码中创建调用 super(context); } public TrendGraph(Context context, AttributeSet attrs) { // 在xm

  • Android自定义可左右滑动和点击的折线图

    前言 前几天有小盆友让我写一个折线图,可以点击,可以左右滑动.对于折线肯定有很多项目都使用过,所以网上肯定也有很多demo,像AndroidChart.HelloChart之类的,功能相当丰富,效果也很赞,但是太重了,其他的小demo又不符合要求,当然了,我写的自定义折线图的思想也有来自这些小demo,对他们表示感谢. 效果图 废话不多说,先上效果图: 效果是不是很赞,如果上图满足你的需求,那就继续往下看. 自定义折线图的步骤: 1.自定义view所需要的属性 确定所需要的自定义view的属性,

  • Android自定义控件实现圆形进度CircleProgressBar

    近日有朋友问我有没有如下图效果的开源控件 相信大家无论是用IOS还是Android,都对这种效果不陌生,很多主流APP都会有这样或类似的效果,之前也打算研究一下这类控件的代码,苦于一直不知道应该怎么搜索这种效果(就是关键词)或者所搜的结果不是自己想要的,所以就一直搁置了下来. 正好朋友需要这种效果,所以就忙里偷闲写了一个类似的.更加常见和适用范围更多的控件,效果如下图所示: 自定义上图所示效果的控件时,其实就是用Canvas绘制不同效果,比如渐变圆弧背景.圆周白色分割线.中间文字等,这篇博客也根

  • Android绘制动态折线图

    所谓动态折线图,就是折线图能随着手指的滑动进行动态绘制,这里很定会产生动画效果.基于这个效果,这里使用SurfaceView进行制图. 实现步奏如下: (1): 这里新建一个绘图ChartView,继承SurfaceView并实现SurfaceHolder.Callback , Runnable接口,主要绘图工作在子线程中完成. (2):现实 SurfaceHolder.Callback接口的三个方法,并在 surfaceCreated中开启子线程进行绘图. (3):重写onTouchEvent

  • Android自定义控件实现方向盘效果

    在很多开发中,为了界面更加的友好,在自定义View的基础上,开发者会开发出各种各样的自定义控件来满足实际开发需要,其中有一种"方向盘"的控件在实际开发中非常常见,便于用户进行一些实际性的方向控制. 在复习参考了许多自定义控件的基础上,我实现了一个最最基本的方向盘空间,并且可以根据方向做出相应的反应.话不多说,先看看效果. 做的有点丑,大家可以看看实际原理,后期再优化具体"方向盘". 空间下面的几行字是我为了确定方向所写的一些参数,基本思想就是在方向盘的中心确定一个坐

  • Android自定义控件实现时钟效果

    在学习安卓群英传自定义控件章节的时候,有一个例子是绘制时钟,在实现了书上的例子后就想看这个时钟能不能动起来. 这里选择延迟一秒发送消息重绘view来实现的动画,对外提供了开启时钟,关闭时钟的方法,当activity执行onResume方法的时候,执行startClock()方法,当移除view或activity执行onStop方法的时候可以执行stopClock()方法. 首先根据view的宽高来确定圆心的位置,并画出一个圆.再通过view高度的一半减去圆的半径,确定刻度的起始位置,选择刻度的长

  • Android自定义控件实现折线图

    本文实例实现一个如下图所示的Android折线图,供大家参考,具体内容如下 首先是控件绘图区域的划分,控件左边取一小部分(控件总宽度的八分之一)绘制表头,右边剩余的部分绘制表格 确定表格的行列数,首先绘制一个三行八列的网格,设置好行列的坐标后开始绘制 /*绘制三条横线*/ for(int i=0;i<3;i++){ canvas.drawLine(textWide, mLineYs[i], totalWidth, mLineYs[i], mPaintLine); } /*绘制八条竖线*/ for

随机推荐