You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MPAndroidChart折线图:如何在X轴时间上方显示天气图标?

解决MPAndroidChart在X轴标签上方绘制天气图标问题

当前你通过Entry绑定图标的方式,会让图标跟随温度数值的Y轴位置显示。要实现X轴标签上方显示图标,需自定义X轴渲染器手动绘制图标:

步骤1:移除Entry图标相关代码

先去掉原代码中获取图标但未使用的部分,Entry仅保留时间索引和温度值:

private fun setTempChart(hour: ArrayList<Hour>, id: String) {
    val entries: MutableList<Entry> = ArrayList()
    for (i in hour.indices) {
        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
        valueFormatter = object : ValueFormatter() {
            override fun getFormattedValue(value: Float): String {
                return String.format(Locale.getDefault(), "%.0f", value)
            }
        }
    }
    // 后续chart基础配置保留
}

步骤2:自定义X轴渲染器

创建自定义XAxisRenderer,重写drawLabels方法,在绘制完时间标签后,在对应位置上方绘制天气图标:

class CustomXAxisRenderer(
    viewPortHandler: ViewPortHandler,
    xAxis: XAxis,
    transformer: Transformer,
    private val hourList: ArrayList<Hour>,
    private val context: Context
) : XAxisRenderer(viewPortHandler, xAxis, transformer) {

    override fun drawLabels(c: Canvas, pos: Float, anchor: PointF) {
        super.drawLabels(c, pos, anchor) // 先绘制默认时间标签

        val dataSet = mChart?.data?.getDataSetByIndex(0) ?: return
        val valueToPixelMatrix = mTransformer.valueToPixelMatrix

        for (i in hourList.indices) {
            val hourData = hourList[i]
            // 复用原有图标获取逻辑
            val iconDrawable = if (hourData.is_day == 1) {
                context.setIconDay(hourData.condition.code)
            } else {
                context.setIconNight(hourData.condition.code)
            } ?: continue

            // 计算X轴对应位置的像素坐标
            val xValue = dataSet.entries[i].x
            val pixelPoint = floatArrayOf(xValue, 0f)
            valueToPixelMatrix.mapPoints(pixelPoint)

            // 配置图标大小和位置(可按需调整)
            val iconSize = 32
            val iconX = pixelPoint[0] - iconSize / 2f // 水平居中
            val iconY = pos - iconSize - 10f // 在时间标签上方留出间距

            // 绘制图标
            iconDrawable.setBounds(
                iconX.toInt(),
                iconY.toInt(),
                (iconX + iconSize).toInt(),
                (iconY + iconSize).toInt()
            )
            iconDrawable.draw(c)
        }
    }
}

步骤3:给Chart设置自定义渲染器

在chart配置代码中,替换默认的X轴渲染器:

chart.apply {
    // 原有基础配置(description、坐标轴、legend等)保持不变
    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
    }
    // 设置自定义X轴渲染器
    xAxisRenderer = CustomXAxisRenderer(
        viewPortHandler,
        xAxis,
        transformer,
        hour,
        requireActivity()
    )
}

注意事项

  • 确保setIconDay和setIconNight返回有效的Drawable对象,若返回资源ID,需通过ContextCompat.getDrawable(context, resId)转换。
  • 图标大小iconSize和位置偏移量(iconY中的-10f)可根据UI需求调整,保证图标与时间标签的间距合适。
  • 代码已通过valueToPixelMatrix处理坐标转换,支持图表缩放适配。

内容的提问来源于stack exchange,提问作者Muaz Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 16:55:27