亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

自定義View之kotlin繪制折線圖實(shí)例教程

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

什么是Kotlin

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

引言

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


再來(lái)看下我實(shí)現(xiàn)的效果


實(shí)現(xiàn)過(guò)程

主要分為x軸和y軸,由效果圖可以看出,x軸主要分為7份,y軸主要分為4份,這樣劃分就比較簡(jiǎn)單的知道每條線的位置,每個(gè)位置的位置了,繪制起來(lái)就很簡(jiǎn)單;

先繪制y軸的四條線和文字

文字有三個(gè),放到一個(gè)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() + "萬(wàn)", mBrokenLineLeft, nowadayHeight + mBrokenLineTop - averageHeight / 2 + mTxtHeight / 2, mTextPaint)
  }
 }

 }
 }
 }

然后繪制x軸的文字

由于文字有6個(gè),我們分為七份,從第一份之后開(kāi)始繪制:

代碼如下:

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ìn)兩個(gè)集合傳入,然后根據(jù)數(shù)據(jù)算出每個(gè)點(diǎn)的坐標(biāo),最后根據(jù)path把每個(gè)點(diǎn)連接起來(lái)就ok了;

代碼如下:

 /**
 * 設(shè)置點(diǎn)的值
 */
 fun setPointValues(valueNew: ArrayList<Int>, valueOld: ArrayList<Int>) {
 this.valueNew = valueNew
 this.valueOld = valueOld
 }
 /**
 * 根據(jù)值計(jì)算在該值的 x,y坐標(biāo)
 */
 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)
  }
  }
 }
 }

最后就是添加動(dòng)畫(huà)了,可有可無(wú),看需求吧

代碼如下:

 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)實(shí)現(xiàn)了,最后加陰影,就更簡(jiǎn)單了,就直接給畫(huà)筆設(shè)置陰影就行了

喜歡請(qǐng)到github點(diǎn)個(gè)贊啦

地址:github (本地下載

總結(jié)

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

相關(guān)文章

最新評(píng)論