Draw Line in recycler view and fill space below | Android | Kotlin

23 views Asked by At

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

enter image description here

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)
0

There are 0 answers