自定义View之kotlin绘制折线图实例教程

 更新时间:2018年09月26日 11:26:18   作者:villa_mou7  
折线图是我们在开发中经常会遇到的一个需求,下面这篇文章主要给大家介绍了关于自定义View之kotlin绘制折线图的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧

什么是Kotlin

Kotlin,它是JetBrains开发的基于JVM的面向对象的语言。2017年的时候被Google推荐Android的官方语言,同时Android studio 3.0正式支持这门语言,在这个编译器上创建一个Kotlin项目,非常方便,甚至可以Java转为Kotlin。

引言

早上看到有个童鞋在群里面发牢骚,说这个自定义view怎么画,不太会,ok,正好我也没事,那我就花两个小时帮你搞定他吧,先看下他要的效果;


再来看下我实现的效果


实现过程

主要分为x轴和y轴,由效果图可以看出,x轴主要分为7份,y轴主要分为4份,这样划分就比较简单的知道每条线的位置,每个位置的位置了,绘制起来就很简单;

先绘制y轴的四条线和文字

文字有三个,放到一个list里面,然后我们均分高度,然后遍历文字集合,根绝不同的高度绘制文字和横线
看下代码:

 /**
 * 绘制边框线和边框文本
 */
 private fun drawBorderLineAndText(canvas: Canvas) {
 when {
 valueTextY.size > 0 -> {
 val averageHeight = mNeedDrawHeight / (valueTextY.size + 1)
 (1..valueTextY.size + 1).forEach { i ->
  val nowadayHeight = averageHeight * (valueTextY.size + 1 - i)
  canvas.drawLine(mBrokenLineLeft, nowadayHeight + mBrokenLineTop, mNeedDrawWidth, nowadayHeight + mBrokenLineTop, mBorderLinePaint)
  if (i < valueTextY.size + 1) {
  val fm = mTextPaint.fontMetrics
  val mTxtHeight = Math.ceil((fm.leading - fm.ascent).toDouble()).toInt()
  canvas.drawText(valueTextY[valueTextY.size - i].toString() + "万", mBrokenLineLeft, nowadayHeight + mBrokenLineTop - averageHeight / 2 + mTxtHeight / 2, mTextPaint)
  }
 }

 }
 }
 }

然后绘制x轴的文字

由于文字有6个,我们分为七份,从第一份之后开始绘制:

代码如下:

private fun drawMonthText(canvas: Canvas) {
 when {
 valueOld.size > 0 -> {
 var month = defaultStartMonth
 for (i in 1..valueOld.size) {
  val averageWidth = (mNeedDrawWidth / (valueOld.size + 1)).toInt()
  val fm = mTextPaint.fontMetrics
  val mTxtHeight = Math.ceil((fm.leading - fm.ascent).toDouble()).toInt()
  canvas.drawText(month.toString() + "月", (averageWidth * i).toFloat(), mNeedDrawHeight - mTxtHeight / 2, mTextPaint)
  month++
 }
 }
 }
 }

最后绘制折线和折现上面的小球

这里我们需要把数据放进两个集合传入,然后根据数据算出每个点的坐标,最后根据path把每个点连接起来就ok了;

代码如下:

 /**
 * 设置点的值
 */
 fun setPointValues(valueNew: ArrayList<Int>, valueOld: ArrayList<Int>) {
 this.valueNew = valueNew
 this.valueOld = valueOld
 }
 /**
 * 根据值计算在该值的 x,y坐标
 */
 fun getPoints(list: ArrayList<Int>): ArrayList<Point> {
 val avaregwidth = mNeedDrawWidth / (list.size + 1)
 val points = ArrayList<Point>(list.size)
 list.indices.forEach { i ->
  val valueY = list[i].toFloat()
  val averaHeight = (mNeedDrawHeight * 3 / 4 / maxValue).toDouble()
  val drawHeight = mNeedDrawHeight * 3 / 4 - (valueY * averaHeight).toFloat() + mBrokenLineTop
  val pointY = drawHeight.toInt()
  val pointX = ((avaregwidth * (i + 1)).toInt() + mBrokenLineLeft).toInt()
  val point = Point(pointX, pointY)
  points.add(point)
 }
 return points
 }
/**
 * 根据值绘制折线
 */
 private fun drawBrokenLine(canvas: Canvas) {
 when {
  valueOld.size > 0 && valueNew.size > 0 -> {
  val mPathOld = Path()
  val mPathNew = Path()
  val mPathOldshadow = Path()
  val mPathNewshadow = Path()
  val pointsOld = getPoints(valueOld)
  val pointsNew = getPoints(valueNew)
  for (i in 0 until mAnimatorValue) {
   val pointOld = pointsOld[i]
   val pointNew = pointsNew[i]
   if (i == 0) {
   mPathOld.moveTo(pointOld.x.toFloat(), pointOld.y.toFloat())
   mPathNew.moveTo(pointNew.x.toFloat(), pointNew.y.toFloat())

   mPathOldshadow.moveTo(pointOld.x.toFloat(), pointOld.y.toFloat())
   mPathNewshadow.moveTo(pointNew.x.toFloat(), pointNew.y.toFloat())
   } else {
   mPathOld.lineTo(pointOld.x.toFloat(), pointOld.y.toFloat())
   mPathNew.lineTo(pointNew.x.toFloat(), pointNew.y.toFloat())

   mPathOldshadow.lineTo(pointOld.x.toFloat(), pointOld.y.toFloat())
   mPathNewshadow.lineTo(pointNew.x.toFloat(), pointNew.y.toFloat())
   }
  }
  mBrokenLinePaint.color = Color.parseColor("#ff5400")
  canvas.drawPath(mPathOld, mBrokenLinePaint)
  mBrokenLinePaint.color = Color.parseColor("#ffff00")
  canvas.drawPath(mPathNew, mBrokenLinePaint)
  }
 }
 }

 /**
 * 绘制线上的圆
 */
 private fun drawLineCircle(canvas: Canvas) {
 when {
  valueOld.size > 0 && valueNew.size > 0 -> {
  val pointsOld = getPoints(valueOld)
  val pointsNew = getPoints(valueNew)
  for (i in 0 until mAnimatorValue) {
   val pointOld = pointsOld[i]
   val pointNew = pointsNew[i]
   mCirclePaint.color = Color.parseColor("#ff5400")
   canvas.drawCircle(pointOld.x.toFloat(), pointOld.y.toFloat(), radius, mCirclePaint)
   mCirclePaint.color = Color.parseColor("#ffff00")
   canvas.drawCircle(pointNew.x.toFloat(), pointNew.y.toFloat(), radius, mCirclePaint)
  }
  }
 }
 }

最后就是添加动画了,可有可无,看需求吧

代码如下:

 private fun initAnimator( size:Int) {
 valueAnimator = ValueAnimator.ofInt(0, size).setDuration(defaultDuration.toLong())
 mUpdateListener = ValueAnimator.AnimatorUpdateListener { animation ->
  mAnimatorValue = animation.animatedValue as Int
  invalidate()
 }
 valueAnimator.addUpdateListener(mUpdateListener)
 valueAnimator.start()
 }

 fun setPointValues(valueNew: ArrayList<Int>, valueOld: ArrayList<Int>) {
 this.valueNew = valueNew
 this.valueOld = valueOld
 initAnimator(valueNew.size)
 }

这样大体效果就已经实现了,最后加阴影,就更简单了,就直接给画笔设置阴影就行了

喜欢请到github点个赞啦

地址:github (本地下载

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • Android 实现通知消息水平播放、无限循环效果

    Android 实现通知消息水平播放、无限循环效果

    Android 实现通知消息水平播放、无限循环效果非常常见,今天小编给大家分享实例代码感兴趣的朋友参考下吧
    2017-08-08
  • android仿iphone主题效果的主菜单

    android仿iphone主题效果的主菜单

    这篇文章主要为大家详细介绍了android仿iphone主题效果的主菜单,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Android实现闪屏页效果

    Android实现闪屏页效果

    这篇文章主要为大家详细介绍了Android实现闪屏页效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • Flutter实现笑嘻嘻的动态表情的示例代码

    Flutter实现笑嘻嘻的动态表情的示例代码

    这篇文章主要为大家介绍了如何利用Flutter实现笑嘻嘻的动态表情,文中的示例代码讲解详细,对我们学习Flutter有一定帮助,感兴趣的可以了解一下
    2022-04-04
  • android使用surfaceview+MediaPlayer播放视频

    android使用surfaceview+MediaPlayer播放视频

    这篇文章主要为大家详细介绍了android使用surfaceview+MediaPlayer播放视频,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • Kotlin类的继承实现详细介绍

    Kotlin类的继承实现详细介绍

    这篇文章主要介绍了Kotlin类的继承,在Java中类的继承默认是继承父类的方法和参数的,但是在kotlin中默认是不继承的,那么我们接下来来验证
    2022-09-09
  • Android rom解包打包工具

    Android rom解包打包工具

    这篇文章主要介绍了Android rom解包打包工具的相关资料,对rom解包打包相关知识感兴趣的朋友可以参考下
    2016-01-01
  • Android编程实现图片背景渐变切换与图层叠加效果

    Android编程实现图片背景渐变切换与图层叠加效果

    这篇文章主要介绍了Android编程实现图片背景渐变切换与图层叠加效果,涉及Android图形特效的相关操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2017-01-01
  • Kotlin中空判断处理操作实例

    Kotlin中空判断处理操作实例

    最近使用kotlin重构项目,遇到了一个小问题,在Java中,可能会遇到判断某个对象是否为空,为空执行一段逻辑,不为空执行另外一段逻辑,下面这篇文章主要给大家介绍了关于Kotlin中空判断处理操作的相关资料,需要的朋友可以参考下
    2022-07-07
  • Android编程实现自定义PopupMenu样式示例【显示图标与设置RadioButton图标】

    Android编程实现自定义PopupMenu样式示例【显示图标与设置RadioButton图标】

    这篇文章主要介绍了Android编程实现自定义PopupMenu样式功能,结合实例形式分析了Android显示图标与设置RadioButton图标相关操作技巧,需要的朋友可以参考下
    2017-01-01

最新评论