如何在Kotlin中利用Google Sheets获取的数据绘制MPAndroidChart折线图?
如何在Kotlin中利用Google Sheets获取的数据绘制MPAndroidChart折线图?
看起来你已经成功搞定了Google Sheets的数据获取,太棒了!接下来咱们一步步把这些零散的数据转换成清晰的折线图——MPAndroidChart确实需要把数据转换成它能识别的格式,别担心,我带你一步步来:
核心思路
MPAndroidChart的折线图需要用LineDataSet来封装每个系列(也就是每个分支的销售数据),再把多个LineDataSet组合成LineData,最后绑定到图表上。咱们先从数据整理开始:
步骤1:整理并转换数据
首先要把获取到的salesList按分支分组,并且按月份排序(折线图必须按时间顺序展示才合理)。然后把每个分支的销售数据转换成MPAndroidChart需要的Entry对象(x轴是月份的索引,y轴是销售额)。
步骤2:修改你的数据回调代码
把下面的代码替换掉你原来Response.Listener里的val datad = LineData(salesList,)那部分,完整的回调代码如下:
Response.Listener { val data = it.getJSONArray("items") for (i in 0 until data.length()) { val salesJasonObject = data.getJSONObject(i) val salesObject = SalesDataModel( salesJasonObject.getString("Date"), salesJasonObject.getString("Branch").trim(), salesJasonObject.getString("SaleAmount").trim().toIntOrNull(), ) salesList.add(salesObject) } // --- 新增的图表处理逻辑开始 --- // 1. 按分支分组,并且每个分支的数据按月份排序 val groupedData = salesList.groupBy { it.Branch } val sortedGroupedData = groupedData.mapValues { entry -> entry.value.sortedBy { it.Date } // 假设Date格式是"2024-01"这类可直接排序的格式 } // 2. 收集所有唯一的月份,作为X轴的标签 val allMonths = salesList.map { it.Date }.distinct().sorted() // 3. 为每个分支创建对应的LineDataSet val lineDataSets = mutableListOf<LineDataSet>() sortedGroupedData.forEach { (branch, sales) -> // 把每个销售数据转换成Entry对象 val entries = sales.mapIndexed { index, sale -> // 处理销售额为null的情况,这里默认设为0 Entry(index.toFloat(), sale.SaleAmount ?: 0f) } // 创建LineDataSet,标签设为分支名称 val dataSet = LineDataSet(entries, branch) // 给不同分支设置不同颜色,方便区分 dataSet.color = when(branch) { "Branch A" -> Color.parseColor("#FF6384") "Branch B" -> Color.parseColor("#36A2EB") "Branch C" -> Color.parseColor("#FFCE56") // 其他分支用随机色 else -> Color.rgb(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256)) } dataSet.setCircleColor(dataSet.color) // 数据点颜色和折线一致 dataSet.lineWidth = 2f // 折线宽度 dataSet.circleRadius = 4f // 数据点大小 lineDataSets.add(dataSet) } // 4. 创建LineData并绑定到图表 val lineData = LineData(lineDataSets) val lineChart = binding.lineChart lineChart.data = lineData // 5. 配置图表样式,让它更美观易用 // X轴设置:放在底部,显示月份标签,旋转避免重叠 val xAxis = lineChart.xAxis xAxis.position = XAxis.XAxisPosition.BOTTOM xAxis.valueFormatter = object : ValueFormatter() { override fun getFormattedValue(value: Float): String { val index = value.toInt() return if (index < allMonths.size) allMonths[index] else "" } } xAxis.setDrawGridLines(false) xAxis.labelRotationAngle = 45f // Y轴设置:左侧显示,从0开始,关闭右侧Y轴 val yAxisLeft = lineChart.axisLeft yAxisLeft.axisMinimum = 0f lineChart.axisRight.isEnabled = false // 图例设置:顶部居中显示 lineChart.legend.apply { isEnabled = true verticalAlignment = Legend.LegendVerticalAlignment.TOP horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER orientation = Legend.LegendOrientation.HORIZONTAL } // 关闭默认的描述文本,启用触摸缩放 lineChart.description.isEnabled = false lineChart.setTouchEnabled(true) lineChart.setPinchZoom(true) // 最后刷新图表 lineChart.invalidate() // --- 新增的图表处理逻辑结束 --- Toast.makeText(this@SalesData, "Data loaded successfully", Toast.LENGTH_LONG).show() }
一些需要注意的细节
- 日期排序问题:如果你的
Date格式是类似"Jan 2024"这种文本格式,直接sortBy会排序错误,需要把Date转换成LocalDate对象再排序,比如:entry.value.sortedBy { LocalDate.parse(it.Date, DateTimeFormatter.ofPattern("MMM yyyy")) } - 空值处理:代码里用了
sale.SaleAmount ?: 0f处理销售额为空的情况,你可以根据需求改成其他默认值或者过滤掉空数据。 - 颜色自定义:如果分支较多,建议用循环生成不同的颜色,避免写一堆
when判断。
备注:内容来源于stack exchange,提问作者Codist
相关产品推荐
相关产品推荐

