最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

什么是Kotlin

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

引言

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


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


實(shí)現(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ìn)兩個集合傳入,然后根據(jù)數(shù)據(jù)算出每個點(diǎn)的坐標(biāo),最后根據(jù)path把每個點(diǎn)連接起來就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)
  }
  }
 }
 }

最后就是添加動畫了,可有可無,看需求吧

代碼如下:

 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)了,最后加陰影,就更簡單了,就直接給畫筆設(shè)置陰影就行了

喜歡請到github點(diǎn)個贊啦

地址:github (本地下載

總結(jié)

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

相關(guān)文章

  • Bootstrap 下拉菜單.dropdown的具體使用方法

    Bootstrap 下拉菜單.dropdown的具體使用方法

    這篇文章主要介紹了Bootstrap 下拉菜單.dropdown的具體使用方法,詳細(xì)講解下拉菜單的交互,有興趣的可以了解一下
    2017-10-10
  • Android 自定義SeekBar 實(shí)現(xiàn)分段顯示不同背景顏色的示例代碼

    Android 自定義SeekBar 實(shí)現(xiàn)分段顯示不同背景顏色的示例代碼

    這篇文章主要介紹了Android 自定義SeekBar 實(shí)現(xiàn)分段顯示不同背景顏色,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • Android實(shí)現(xiàn)下載進(jìn)度條效果

    Android實(shí)現(xiàn)下載進(jìn)度條效果

    vivo商店在下載應(yīng)用的時候,底部有一個圓角矩形的下載進(jìn)度條,中間有一個進(jìn)度文字,而且進(jìn)度和文字交匯的時候,交匯部分的文字會從藍(lán)色邊為白色,會有一種一半白色字,一半藍(lán)色字的效果。本文將仿照該樣式實(shí)現(xiàn)一個
    2021-06-06
  • Android橫豎屏幕切換生命周期詳解

    Android橫豎屏幕切換生命周期詳解

    這篇文章主要為大家詳細(xì)介紹了Android橫豎屏幕切換生命周期,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android LayoutInflater深入分析及應(yīng)用

    Android LayoutInflater深入分析及應(yīng)用

    這篇文章主要介紹了Android LayoutInflater分析的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • 詳解Android studio中正確引入so文件的方法

    詳解Android studio中正確引入so文件的方法

    本篇文章主要介紹了Android studio中正確引入so文件的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • android系統(tǒng)分享的自定義功能的示例代碼

    android系統(tǒng)分享的自定義功能的示例代碼

    本篇文章主要介紹了android系統(tǒng)分享的自定義功能的示例代碼,非常具有實(shí)用價值,需要的朋友可以參考下
    2017-08-08
  • Android中volley封裝實(shí)踐記錄

    Android中volley封裝實(shí)踐記錄

    這篇文章主要給大家介紹了關(guān)于Android中volley封裝實(shí)踐的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • Android Accessibility 輔助功能簡單介紹

    Android Accessibility 輔助功能簡單介紹

    這篇文章主要介紹了Android Accessibility 輔助功能簡單介紹的相關(guān)資料,文字轉(zhuǎn)語音,觸覺反饋,手勢操作,軌跡球和手柄操作,需要的朋友可以參考下
    2016-11-11
  • ANDROID 完美退出APP的實(shí)例代碼

    ANDROID 完美退出APP的實(shí)例代碼

    這篇文章介紹了ANDROID 完美退出APP的實(shí)例代碼,有需要的朋友可以參考一下
    2013-08-08

最新評論

南丹县| 邹平县| 开原市| 桂东县| 桑日县| 汶上县| 青神县| 杨浦区| 怀化市| 泗阳县| 丁青县| 简阳市| 华池县| 吉首市| 时尚| 吴忠市| 汽车| 大厂| 类乌齐县| 南雄市| 县级市| 平阳县| 怀来县| 信丰县| 安平县| 监利县| 腾冲县| 密云县| 奈曼旗| 阳新县| 乐清市| 汝南县| 九台市| 丹寨县| 北川| 宁远县| 临夏县| 勃利县| 图木舒克市| 滁州市| 思茅市|