Android自定義View之漸變色折線圖的實(shí)現(xiàn)
前言
在之前的項(xiàng)目中,有做過一個需求,需要實(shí)現(xiàn)一個顏色漸變的折線圖。當(dāng)時項(xiàng)目中使用的圖表庫是MPAndroidChart,但是該庫沒有提供合適的方法來實(shí)現(xiàn)想要的效果,因此只能通過自定義view來實(shí)現(xiàn)。
通過這篇文章記錄一下,便于之后需要實(shí)現(xiàn)類似的效果時查找使用。
如何實(shí)現(xiàn)
通過創(chuàng)建LinearGradient來實(shí)現(xiàn)顏色漸變,并將之設(shè)置到畫筆Paint的著色器Shader,繪制想要的路徑即可實(shí)現(xiàn)該效果。
實(shí)現(xiàn)代碼如下:
class GradientLineChart : View {
private var viewWidth: Int = 0
private var viewHeight: Int = 0
private var chartWidth: Int = 0
private var chartHeight: Int = 0
/**
* 折線寬度
*/
private var lineWidth: Float = 0f
/**
* 網(wǎng)格線寬度
*/
private var gridLineWidth: Float = 0f
/**
* 網(wǎng)格線顏色
*/
private var gridLineColor: Int = 0
/**
* 背景顏色
*/
private var backgroundColorRes: Int = 0
private var linePaint: Paint? = null
private var gridLinePaint: Paint? = null
private var gradientColor: IntArray? = null
private val rectF = RectF()
private val linePath = Path()
private val lineValueList = ArrayList<LineEntity>()
constructor(context: Context?) : this(context, null)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
lineValueList.add(LineEntity(3f, 28f))
lineValueList.add(LineEntity(7f, 2f))
lineValueList.add(LineEntity(14f, 18f))
lineValueList.add(LineEntity(17f, 12f))
lineValueList.add(LineEntity(22f, 21f))
context?.let {
gradientColor = intArrayOf(
ContextCompat.getColor(it, R.color.color_FFD200),
ContextCompat.getColor(it, R.color.color_FF2600),
ContextCompat.getColor(it, R.color.color_49E284),
ContextCompat.getColor(it, R.color.color_00A5FF)
)
}
initAttr(attrs, defStyleAttr)
initPaint()
}
private fun initAttr(attrs: AttributeSet?, defStyleAttr: Int) {
val typeArray =
context.theme.obtainStyledAttributes(attrs, R.styleable.GradientLineChart, defStyleAttr, 0)
lineWidth = typeArray.getDimension(
R.styleable.GradientLineChart_tc_lineWidth,
DensityUtil.dp2Px(2).toFloat()
)
gridLineWidth = typeArray.getDimension(
R.styleable.GradientLineChart_tc_grid_line_width,
DensityUtil.dp2Px(1).toFloat()
)
gridLineColor = typeArray.getColor(
R.styleable.GradientLineChart_tc_grid_line_color,
ContextCompat.getColor(context, R.color.color_1Affffff)
)
backgroundColorRes = typeArray.getColor(
R.styleable.GradientLineChart_tc_background_color,
ContextCompat.getColor(context, R.color.color_23242a)
)
typeArray.recycle()
}
private fun initPaint() {
linePaint = Paint()
linePaint?.isAntiAlias = true
linePaint?.style = Paint.Style.STROKE
linePaint?.strokeWidth = lineWidth
gridLinePaint = Paint()
gridLinePaint?.isAntiAlias = true
gridLinePaint?.style = Paint.Style.FILL
gridLinePaint?.color = gridLineColor
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
viewWidth = MeasureSpec.getSize(widthMeasureSpec)
viewHeight = MeasureSpec.getSize(heightMeasureSpec)
//MUST CALL THIS
setMeasuredDimension(viewWidth, viewHeight)
chartWidth = viewWidth - paddingStart - paddingEnd
chartHeight = viewHeight - paddingTop - paddingBottom
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
//設(shè)置畫布背景色
canvas?.drawColor(backgroundColorRes)
//繪制網(wǎng)格線
drawGradLine(canvas)
//繪制折線
drawLine(canvas)
}
/**
* 繪制網(wǎng)格線
*/
private fun drawGradLine(canvas: Canvas?) {
gridLinePaint?.let {
val yGridValues = 7
val xGridValues = 6
//Y軸網(wǎng)格線間距
val yGridDistance = (chartHeight - yGridValues * gridLineWidth) / (yGridValues - 1)
for (index in 0 until yGridValues) {
val left = paddingStart.toFloat()
val top = paddingTop.toFloat() + index * yGridDistance + index * gridLineWidth
val right = left + chartWidth
val bottom = top + gridLineWidth
rectF.set(left, top, right, bottom)
canvas?.drawRect(rectF, it)
}
//X軸網(wǎng)格線間距
val xGridDistance = (chartWidth - xGridValues * gridLineWidth) / (xGridValues - 1)
for (index in 0 until xGridValues) {
val left = paddingStart + xGridDistance * index + gridLineWidth * index
val top = paddingTop.toFloat()
val right = left + gridLineWidth
val bottom = top + chartHeight
rectF.set(left, top, right, bottom)
canvas?.drawRect(rectF, gridLinePaint!!)
}
}
}
/**
* 繪制折線
*/
private fun drawLine(canvas: Canvas?) {
val yGridValues = 7
val xGridValues = 6
val yGridDistance = (chartHeight - yGridValues * gridLineWidth) / (yGridValues - 1)
val xGridDistance = (chartWidth - xGridValues * gridLineWidth) / (xGridValues - 1)
for ((index, linePoint) in lineValueList.withIndex()) {
val pointX =
((linePoint.xValue - 5 * index) / 5) * xGridDistance + (xGridDistance * index)
val pointY =
chartHeight - (linePoint.yValue / 30 * (yGridDistance * 6))
if (index == 0) {
linePath.moveTo(pointX, pointY)
} else {
linePath.lineTo(pointX, pointY)
}
}
linePaint?.shader = createLineGradient(gradientColor!!)
canvas?.drawPath(linePath, linePaint!!)
}
private fun createLineGradient(gradientColor: IntArray): LinearGradient {
return LinearGradient(
0f,
0f,
0f,
viewHeight.toFloat(),
gradientColor,
null,
Shader.TileMode.CLAMP
)
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="GradientLineChart">
<!--線寬度-->
<attr name="tc_lineWidth" format="dimension" />
<!--網(wǎng)格線寬度-->
<attr name="tc_grid_line_width" format="dimension" />
<!--網(wǎng)格線顏色-->
<attr name="tc_grid_line_color" format="color" />
<!--等級顏色指示器寬度-->
<attr name="tc_level_indicator_width" format="dimension" />
<!--背景顏色-->
<attr name="tc_background_color" format="color" />
</declare-styleable>
</resources>效果如下圖:

總結(jié)
到此這篇關(guān)于Android自定義View之漸變色折線圖的文章就介紹到這了,更多相關(guān)Android漸變色折線圖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
實(shí)例探究Android開發(fā)中Fragment狀態(tài)的保存與恢復(fù)方法
這篇文章主要介紹了實(shí)例探究Android開發(fā)中Fragment狀態(tài)的保存與恢復(fù)方法,或許開發(fā)者們對Fragment的操作都比較熟悉,但onSaveInstanceState()方法并不能夠很好地保存Fragment狀態(tài),需要的朋友可以參考下2016-04-04
Android 復(fù)制文本內(nèi)容到系統(tǒng)剪貼板的最簡單實(shí)例(分享)
下面小編就為大家?guī)硪黄狝ndroid 復(fù)制文本內(nèi)容到系統(tǒng)剪貼板的最簡單實(shí)例(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
Android?Flutter實(shí)現(xiàn)有趣的頁面滾動效果
Flutter提供了?CustomScrollView?來粘合多個滑動組件,并且可以實(shí)現(xiàn)更有趣的滑動效果,本文就來為大家詳細(xì)講講實(shí)現(xiàn)的方法,需要的可以參考一下2022-06-06

