欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

自定義View之kotlin繪制折線圖實例教程

 更新時間:2018年09月26日 11:26:18   作者:villa_mou7  
折線圖是我們在開發(fā)中經(jīng)常會遇到的一個需求,下面這篇文章主要給大家介紹了關(guān)于自定義View之kotlin繪制折線圖的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧

什么是Kotlin

Kotlin,它是JetBrains開發(fā)的基于JVM的面向?qū)ο蟮恼Z言。2017年的時候被Google推薦Android的官方語言,同時Android studio 3.0正式支持這門語言,在這個編譯器上創(chuàng)建一個Kotlin項目,非常方便,甚至可以Java轉(zhuǎn)為Kotlin。

引言

早上看到有個童鞋在群里面發(fā)牢騷,說這個自定義view怎么畫,不太會,ok,正好我也沒事,那我就花兩個小時幫你搞定他吧,先看下他要的效果;


再來看下我實現(xiàn)的效果


實現(xiàn)過程

主要分為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++
 }
 }
 }
 }

最后繪制折線和折現(xiàn)上面的小球

這里我們需要把數(shù)據(jù)放進兩個集合傳入,然后根據(jù)數(shù)據(jù)算出每個點的坐標,最后根據(jù)path把每個點連接起來就ok了;

代碼如下:

 /**
 * 設置點的值
 */
 fun setPointValues(valueNew: ArrayList<Int>, valueOld: ArrayList<Int>) {
 this.valueNew = valueNew
 this.valueOld = valueOld
 }
 /**
 * 根據(jù)值計算在該值的 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
 }
/**
 * 根據(jù)值繪制折線
 */
 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)
 }

這樣大體效果就已經(jīng)實現(xiàn)了,最后加陰影,就更簡單了,就直接給畫筆設置陰影就行了

喜歡請到github點個贊啦

地址:github (本地下載

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

最新評論