I have made Item decorator for drawing line in recycler view it works well. Now I want to fill everything below the line. Also I want to make line connection more smooth, I have tried increasing the PATH_CORNER_RADIUS_IN_DP
but seems not working well, maybe I'm missing something
package com.meteosolutions.vojvodinameteo.recyclers
import android.content.Context
import android.content.res.Resources
import android.graphics.Canvas
import android.graphics.CornerPathEffect
import android.graphics.Paint
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.meteosolutions.vojvodinameteo.R
import com.meteosolutions.vojvodinameteo.model.data.fragmentMain.HourlyForecastData
import kotlin.math.roundToInt
private const val STROKE_WIDTH = 7f
private const val PATH_CORNER_RADIUS_IN_DP = 60
private const val CHILD_HEADER_OR_FOOTER_HEIGHT_IN_DP = 278
internal class TemperatureLineItemDecorator(temperatureList: List<HourlyForecastData>, context: Context) :
RecyclerView.ItemDecoration() {
private val drawPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
strokeWidth = STROKE_WIDTH
style = Paint.Style.STROKE
strokeJoin = Paint.Join.ROUND
strokeCap = Paint.Cap.ROUND
color = ContextCompat.getColor(context, R.color.white)
pathEffect = CornerPathEffect(PATH_CORNER_RADIUS_IN_DP.dpToPx)
}
private val normalizedTemperatureValues = normalizeValues(temperatureList)
override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
super.onDraw(canvas, parent, state)
for (childIndex in 0 until parent.childCount) {
val childView = parent.getChildAt(childIndex)
val dataIndex = parent.getChildAdapterPosition(childView)
val childViewHeight = childView.height
canvas.drawLine(
childView.left.toFloat(),
calculateYValue(dataIndex, childViewHeight),
childView.right.toFloat(),
calculateYValue(getDataIndexOfNextChild(dataIndex), childViewHeight),
drawPaint
)
}
}
private fun getDataIndexOfNextChild(currentChildDataIndex: Int): Int {
val nextChildDataIndex = currentChildDataIndex + 1
return if (nextChildDataIndex >= normalizedTemperatureValues.size) {
currentChildDataIndex
} else {
nextChildDataIndex
}
}
private fun calculateYValue(dataIndex: Int, childViewHeight: Int): Float {
val graphHeight = childViewHeight - (CHILD_HEADER_OR_FOOTER_HEIGHT_IN_DP / 2).dpToPx
val graphStartHeightDelta = CHILD_HEADER_OR_FOOTER_HEIGHT_IN_DP.dpToPx
return ((1 - normalizedTemperatureValues[dataIndex] * graphHeight + graphStartHeightDelta))
}
private fun normalizeValues(hourlyForecastData: List<HourlyForecastData>): List<Float> {
val minTemperature = hourlyForecastData.minBy { it.temp.roundToInt() }
val maxTemperature = hourlyForecastData.maxBy { it.temp.roundToInt() }
if (minTemperature.temp.roundToInt() >= maxTemperature.temp.roundToInt()) {
return hourlyForecastData.map { 0.5f }
}
val range = maxTemperature.temp - minTemperature.temp
return hourlyForecastData.map {
val relativeValue = it.temp - minTemperature.temp
return@map (relativeValue / range).toFloat()
}
}
}
val Int.dpToPx: Float
get() = (this * Resources.getSystem().displayMetrics.density)