kotlin 我有一个折线图,我想用它来显示温度,但我想在X轴上显示图标和时间

qhhrdooz  于 2022-12-04  发布在  Kotlin
关注(0)|答案(1)|浏览(145)

我想要实现的目标

我有什么
我想在时间上方的X轴上显示图标,但折线图会将图标放在显示温度的值上。我搜索了很多,但没有找到答案。任何帮助都将不胜感激。我尝试了很多方法,但都是在静脉中。

private fun setTempChart(hour: ArrayList<Hour>, id: String) {
        val entries: MutableList<Entry> = ArrayList()
        for (i in hour.indices) {
            val code = hour[i].condition.code
            val icon =
                if (hour[i].is_day == 1) requireActivity().setIconDay(code) else requireActivity().setIconNight(
                    code
                )
            entries.add(Entry(i.toFloat(), sharedPreference.temp?.let {
                hour[i].temp_c.setCurrentTemperature(
                    it
                ).toFloat()
            }!!))
        }
        val dataSet = LineDataSet(entries, "")
        dataSet.apply {
            lineWidth = 0f
            setDrawCircles(false)
            setDrawCircleHole(false)
            isHighlightEnabled = false
            valueTextColor = Color.WHITE
            setColors(Color.WHITE)
            valueTextSize = 12f
            mode = LineDataSet.Mode.CUBIC_BEZIER
            setDrawFilled(true)
            fillColor = Color.WHITE
            valueTypeface = typeface
            isDrawIconsEnabled
            setDrawIcons(true)
            valueFormatter = object : ValueFormatter() {
                override fun getFormattedValue(value: Float): String {
                    return String.format(Locale.getDefault(), "%.0f", value)
                }
            }
        }
        val lineData = LineData(dataSet)
        chart.apply {
            description.isEnabled = false
            axisLeft.setDrawLabels(false)
            axisRight.setDrawLabels(false)
            legend.isEnabled = false
            axisLeft.setDrawGridLines(false)
            axisRight.setDrawGridLines(false)
            axisLeft.setDrawAxisLine(false)
            axisRight.setDrawAxisLine(false)
            setScaleEnabled(false)
            data = lineData
            setVisibleXRange(8f, 8f)
            animateY(1000)
            xAxis.apply {
                setDrawAxisLine(false)
                textColor = Color.WHITE
                setDrawGridLines(false)
                setDrawLabels(true)
                position = XAxis.XAxisPosition.BOTTOM
                textSize = 12f
                valueFormatter = MyAxisFormatter(hour, id)
                isGranularityEnabled = true
                granularity = 1f
                labelCount = entries.size
            }
        }
    }

我正在使用MPDandroidChart库

gupuwyp2

gupuwyp21#

没有一种很好的内置方式来绘制这样的图标,但是可以通过对LineChartRenderer进行自定义扩展并覆盖drawExtras来实现。然后,可以从R.drawable.X获取图标,并将其绘制在画布上的任意位置。需要做一些工作来确定将它们放置在何处以与数据点对齐。但是您可以从drawCircles复制逻辑来找到它。

自定义渲染器示例

inner class MyRenderer(private val context: Context, chart: LineDataProvider, animator: ChartAnimator, viewPortHandler: ViewPortHandler)
    : LineChartRenderer(chart, animator, viewPortHandler) {

    private var buffer: FloatArray = listOf(0f,0f).toFloatArray()

    override fun drawExtras(c: Canvas) {
        super.drawExtras(c)

        // get the icons you want to draw
        val cloudy = ContextCompat.getDrawable(context, R.drawable.cloudy) ?: return
        val sunny = ContextCompat.getDrawable(context, R.drawable.sunny) ?: return
        
        // Determine icon width in pixels
        val w = 100f // don't hard-code these in pixels
        val h = 100f

        val dataSets = mChart.lineData.dataSets
        val phaseY = mAnimator.phaseY

        for(dataSet in dataSets) {
            mXBounds.set(mChart, dataSet)
            val boundsRange = mXBounds.range + mXBounds.min
            val transformer = mChart.getTransformer(dataSet.axisDependency)

            for(j in mXBounds.min .. boundsRange) {
                val e = dataSet.getEntryForIndex(j) ?: break

                buffer[0] = e.x
                buffer[1] = e.y * phaseY

                transformer.pointValuesToPixel(buffer)

                if( !mViewPortHandler.isInBoundsRight(buffer[0])) {
                    break
                }

                if( !mViewPortHandler.isInBoundsLeft(buffer[0]) || !mViewPortHandler.isInBoundsY(buffer[1])) {
                    continue
                }

                // Draw the icon centered under the data point, but at a fixed
                // vertical position (arbitrary 650 here).
                val left = (buffer[0]-w/2).roundToInt()
                val right = (buffer[0]+w/2).roundToInt()
                val top = 650
                val bottom = (top+h).roundToInt()

                // Use whatever logic you want to select which icon
                // to use at each position
                val icon = if( e.y > 68f ) {
                    sunny
                }
                else {
                    cloudy
                }

                icon.setBounds(left, top, right, bottom)
                icon.draw(c)
            }
        }

    }
}

使用自定义渲染器

val chart = findViewById<LineChart>(R.id.chart)

chart.axisRight.isEnabled = false
val yAx = chart.axisLeft
yAx.setDrawLabels(false)
yAx.setDrawGridLines(false)
yAx.setDrawAxisLine(false)
yAx.axisMinimum = 40f
yAx.axisMaximum = 80f

val xAx = chart.xAxis
xAx.setDrawLabels(false)
xAx.position = XAxis.XAxisPosition.BOTTOM
xAx.setDrawGridLines(false)
xAx.setDrawAxisLine(false)
xAx.axisMinimum = 0.5f
xAx.axisMaximum = 5.5f
xAx.granularity = 0.5f

val x = listOf(0,1,2,3,4,5,6)
val y = listOf(60,65,66,70,65,50,55)
val e = x.zip(y).map { Entry(it.first.toFloat(), it.second.toFloat())}
val line = LineDataSet(e, "temp")
line.setDrawValues(true)
line.setDrawCircles(false)
line.circleRadius = 20f // makes the text offset up
line.valueTextSize = 20f
line.color = Color.BLACK
line.lineWidth = 2f
line.setDrawFilled(true)
line.fillColor = Color.BLACK
line.fillAlpha = 50
line.mode = LineDataSet.Mode.CUBIC_BEZIER
line.valueFormatter = object : ValueFormatter() {
    override fun getFormattedValue(value: Float): String {
        return "%.0f F".format(value)
    }
}

chart.renderer = MyRenderer(this, chart, chart.animator, chart.viewPortHandler)

chart.data = LineData(line)
chart.description.isEnabled = false
chart.legend.isEnabled = false

提供所需效果

相关问题