当前位置: 移动技术网 > IT编程>移动开发>Android > 自定义View之kotlin绘制折线图实例教程

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

2019年08月02日  | 移动技术网IT编程  | 我要评论

同等学历申请硕士,月之恋人结局,五十岚胜人

什么是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 ()

总结

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网