当前位置: 首页 > article >正文

App接入图表:MPAndroidChart,如何创建柱状图、双柱状图以及折线图

目录:

  1. 需求是什么?
  2. 创建柱状图(两条)。
  3. 创建双柱状图(间距)
  4. 创建折线图

一、需求是什么?

我们想实现数据统计、或者物料统计,那么就需要使用到图表,而MPAndroidChart框架可以提供框架给我们进行开发。比如可以实现如下:
在这里插入图片描述在这里插入图片描述在这里插入图片描述


二、引入依赖

implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'

三、创建柱状图(两条):销售数据和销售量

3.1 XML

    <com.github.mikephil.charting.charts.BarChart
        android:id="@+id/barChart"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

3.2 创建图表

流程:
(1)初始化 BarChart
(2)配置图表样式【重点】
(3)生成 28 天的销售测试数据
(4)给柱状图设置数据【重点】

package com.example.mpandroidchartdemo
import android.graphics.Color
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.github.mikephil.charting.charts.BarChart
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.BarData
import com.github.mikephil.charting.data.BarDataSet
import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter
import com.github.mikephil.charting.formatter.ValueFormatter

class MainActivity : AppCompatActivity() {

    private lateinit var barChart: BarChart

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 1.初始化 BarChart
        barChart = findViewById(R.id.barChart)

        // 2. 配置图表样式:X轴(下方数据),两Y轴(左侧数据)
        setupBarChart()

        // 3. 生成 28 天的销售数据
        val salesData = generateSalesData()

        // 4. 设置柱状图数据
        setBarChartData(salesData)
    }

    /**
     * 配置 BarChart 的基本样式
     */
    private fun setupBarChart() {
        // 基本配置
        barChart.setDrawGridBackground(false) // 不绘制网格背景
        barChart.description.isEnabled = false // 禁用描述
        barChart.legend.isEnabled = true // 启用图例
        barChart.setPinchZoom(false) // 禁用捏合缩放
        barChart.setDrawBarShadow(false) // 不绘制柱状图阴影
        barChart.setDrawValueAboveBar(true) // 在柱状图上方显示数值

        // 配置 X 轴
        val xAxis = barChart.xAxis
        xAxis.position = XAxis.XAxisPosition.BOTTOM // X 轴显示在底部
        xAxis.setDrawGridLines(false) // 不绘制 X 轴网格线
        xAxis.granularity = 1f // 设置最小间隔为 1
        xAxis.labelCount = 28 // 显示 28 个标签
        xAxis.valueFormatter = IndexAxisValueFormatter(getXAxisLabels()) // 设置 X 轴标签 这是 MPAndroidChart 库提供的一个内置格式化器类,专门用于处理基于索引(顺序位置)的标签。

        // ---------注意    Y轴是有两个的。
        // 配置左侧 Y 轴
        val leftAxis = barChart.axisLeft
        leftAxis.setDrawGridLines(true) // 绘制 Y 轴网格线
        leftAxis.axisMinimum = 0f // Y 轴从 0 开始

        // 禁用右侧 Y 轴 默认是会显示的。
        val rightAxis = barChart.axisRight
        rightAxis.isEnabled = false
    }

    /**
     * 生成 28 天的模拟销售数据
     * @return List<Pair<Float, Float>>,Pair 的第一个值是售卖数量,第二个值是售卖金额
     */
    private fun generateSalesData(): List<Pair<Float, Float>> {
        return List(28) { index ->
            Pair((50 + index * 2).toFloat(), (1000 + index * 50).toFloat())
        }
    }

    /**
     * 生成 X 轴标签(1 到 28 天) Day 1 Day2 Day3
     * @return List<String>,X 轴的标签列表
     */
    private fun getXAxisLabels(): List<String> {
        return List(28) { index -> "Day ${index + 1}" }
    }

    /**
     * 设置柱状图数据
     * @param salesData 28 天的销售数据
     */
    private fun setBarChartData(salesData: List<Pair<Float, Float>>) {
        // 1. 创建 BarEntry 列表 --将销售数据转换为 BarEntry
        val entriesQuantity = mutableListOf<BarEntry>() // 售卖数量
        val entriesAmount = mutableListOf<BarEntry>()  // 售卖金额

        // 2. 遍历销售数据,转换为 BarEntry---填充数据
        salesData.forEachIndexed { index, data ->
            entriesQuantity.add(BarEntry(index.toFloat(), data.first))  // 售卖数量
            entriesAmount.add(BarEntry(index.toFloat(), data.second)) // 售卖金额
        }
        // 3. 创建 BarDataSet
        val dataSetQuantity = BarDataSet(entriesQuantity, "售卖数量").apply {
            color = Color.BLUE // 设置柱状图颜色
            valueTextColor = Color.BLACK // 设置数值文字颜色
            valueTextSize = 12f // 设置数值文字大小
            valueFormatter = object : ValueFormatter() {
                override fun getFormattedValue(value: Float): String {
                    return value.toInt().toString() // 格式化售卖数量
                }
            }
        }

        val dataSetAmount = BarDataSet(entriesAmount, "售卖金额").apply {
            color = Color.GREEN // 设置柱状图颜色
            valueTextColor = Color.BLACK // 设置数值文字颜色
            valueTextSize = 12f // 设置数值文字大小
            valueFormatter = object : ValueFormatter() {
                override fun getFormattedValue(value: Float): String {
                    return value.toInt().toString() // 格式化售卖金额
                }
            }
        }

        // 创建 BarData
        val barData = BarData(dataSetQuantity, dataSetAmount).apply {
            barWidth = 0.4f // 设置柱状图宽度 // 设置柱子的宽度
        }

        // 设置数据到 BarChart
        barChart.data = barData
        barChart.invalidate() // 刷新图表
    }
}

1、关于配置图表样式
(1)首先进行基本的配置:关于网格,背景等等
(2)配置X轴,也就是下方的轴,day1 day2 day3这些。
(3)配置Y轴,注意,Y轴是有两个的,分左右两侧。

2、给柱状图设置数据
(1)BarEntry是什么:表示柱状图中单个柱子的数据点。每个 BarEntry 包含了该柱子在 X 轴上的位置以及对应的高度(Y 轴值)。

* 主要属性:
     *     x: 柱子在 X 轴上的位置,通常是一个浮点数。如果 X 轴是类别标签,可以使用索引(如 0, 1, 2, ...)。
     *     y: 柱子的高度,即 Y 轴上的数值。
     *     icon: 可选,柱子上方的图标(如气泡图标)。
     *     data: 可选,附加数据,可以存储任何对象(如字符串、整数等)。
     *BarDataSet 是一组 BarEntry 的集合,代表柱状图中的一组柱子。

(2)BarDataSet 是什么:表示一组 BarEntry 的集合,代表柱状图中的一组柱子。这个例子中我们有两组柱子,一组是销售数据,一组是销售量。

*主要属性:
     *     entries: 包含一组 BarEntry 对象。
     *     label: 数据集的标签,用于图例和描述。
     *     color: 柱子的颜色。
     *     highlightColor: 高亮时的颜色。
     *     barShadowColor: 柱子阴影的颜色。
     *     barWidth: 柱子的宽度,范围在 0.2 到 1.0 之间。

(3)BarData 是用于管理和组织柱状图(Bar Chart)中所有数据集(BarDataSet)的核心类。它负责将多个数据集整合在一起,并将其应用到图表中进行显示,可以设置柱子的宽度和间距。调用 barChart.invalidate() 就会 刷新图表。

在这里插入图片描述


四、创建双柱状图(间距)

关于间距我们使用BarData 来设置。
在这里插入图片描述设置间距这里一定要注意,宽度和间距一定要匹配,不然就会出现位置对不上的问题。

   // 创建 BarData
        val barData = BarData( dataSetAmount,dataSetQuantity).apply {
            val amount = 2//多少条柱,就写多少,这里我们是填充两条
            val groupSpace = 0.3f //柱状图组之间的间距
            val barWidth1 = (1f - groupSpace) / amount
            val barSpace = 0f
            barWidth = barWidth1 // 设置柱状图宽度 // 设置柱子的宽度
            groupBars(0f, groupSpace, barSpace)//用于组之间的间距。

        }

五、折线图

5.1 XML


    <com.github.mikephil.charting.charts.LineChart
        android:id="@+id/lineChart"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="16dp" />

5.2 代码

整体的流程是差不多的,只不过控件换了。

import android.graphics.Color
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter
import com.github.mikephil.charting.formatter.ValueFormatter

class MainActivity : AppCompatActivity() {

    private lateinit var lineChart: LineChart

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 初始化 LineChart
        lineChart = findViewById(R.id.lineChart)

        // 配置图表样式
        setupLineChart()

        // 生成 28 天的销售数据
        val salesData = generateSalesData()

        // 设置折线图数据
        setLineChartData(salesData)
    }

    /**
     * 配置 LineChart 的基本样式
     */
    private fun setupLineChart() {
        // 基本配置
        lineChart.setDrawGridBackground(false) // 不绘制网格背景
        lineChart.description.isEnabled = false // 禁用描述
        lineChart.legend.isEnabled = true // 启用图例
        lineChart.setPinchZoom(true) // 启用捏合缩放
        lineChart.setDrawMarkers(true) // 启用数据点标记

        // 配置 X 轴
        val xAxis = lineChart.xAxis
        xAxis.position = XAxis.XAxisPosition.BOTTOM // X 轴显示在底部
        xAxis.setDrawGridLines(false) // 不绘制 X 轴网格线
        xAxis.granularity = 1f // 设置最小间隔为 1
        xAxis.labelCount = 28 // 显示 28 个标签
        xAxis.valueFormatter = IndexAxisValueFormatter(getXAxisLabels()) // 设置 X 轴标签

        // 配置左侧 Y 轴
        val leftAxis = lineChart.axisLeft
        leftAxis.setDrawGridLines(true) // 绘制 Y 轴网格线
        leftAxis.axisMinimum = 0f // Y 轴从 0 开始

        // 禁用右侧 Y 轴
        val rightAxis = lineChart.axisRight
        rightAxis.isEnabled = false
    }

    /**
     * 生成 28 天的模拟销售数据
     * @return List<Pair<Float, Float>>,Pair 的第一个值是售卖数量,第二个值是售卖金额
     */
    private fun generateSalesData(): List<Pair<Float, Float>> {
        return List(28) { index ->
            Pair((50 + index * 2).toFloat(), (1000 + index * 50).toFloat())
        }
    }

    /**
     * 生成 X 轴标签(1 到 28 天)
     * @return List<String>,X 轴的标签列表
     */
    private fun getXAxisLabels(): List<String> {
        return List(28) { index -> "Day ${index + 1}" }
    }

    /**
     * 设置折线图数据
     * @param salesData 28 天的销售数据
     */
    private fun setLineChartData(salesData: List<Pair<Float, Float>>) {
        // 创建 Entry 列表
        val entriesQuantity = mutableListOf<Entry>() // 售卖数量
        val entriesAmount = mutableListOf<Entry>()  // 售卖金额

        // 遍历销售数据,转换为 Entry
        salesData.forEachIndexed { index, data ->
            entriesQuantity.add(Entry(index.toFloat(), data.first))  // 售卖数量
            entriesAmount.add(Entry(index.toFloat(), data.second)) // 售卖金额
        }

        // 创建 LineDataSet
        val dataSetQuantity = LineDataSet(entriesQuantity, "售卖数量").apply {
            color = Color.BLUE // 设置折线颜色
            valueTextColor = Color.BLACK // 设置数值文字颜色
            valueTextSize = 12f // 设置数值文字大小
            lineWidth = 2f // 设置折线宽度
            setCircleColor(Color.BLUE) // 设置数据点颜色
            circleRadius = 4f // 设置数据点半径
            setDrawValues(true) // 显示数值
            valueFormatter = object : ValueFormatter() {
                override fun getFormattedValue(value: Float): String {
                    return value.toInt().toString() // 格式化售卖数量
                }
            }
        }

        val dataSetAmount = LineDataSet(entriesAmount, "售卖金额").apply {
            color = Color.GREEN // 设置折线颜色
            valueTextColor = Color.BLACK // 设置数值文字颜色
            valueTextSize = 12f // 设置数值文字大小
            lineWidth = 2f // 设置折线宽度
            setCircleColor(Color.GREEN) // 设置数据点颜色
            circleRadius = 4f // 设置数据点半径
            setDrawValues(true) // 显示数值
            valueFormatter = object : ValueFormatter() {
                override fun getFormattedValue(value: Float): String {
                    return value.toInt().toString() // 格式化售卖金额
                }
            }
        }

        // 创建 LineData
        val lineData = LineData(dataSetQuantity, dataSetAmount)

        // 设置数据到 LineChart
        lineChart.data = lineData
        lineChart.invalidate() // 刷新图表
    }
}

在这里插入图片描述


http://www.kler.cn/a/551628.html

相关文章:

  • C学习, 排序算法
  • @Param
  • 航空公司客户价值分析
  • LLM论文笔记 12: Teaching Arithmetic to Small Transformers
  • 使用Linux创作第一个小程序--进度条
  • 虚幻蓝图解决抗锯齿方案
  • 基于微信小程序的宿舍报修管理系统设计与实现,SpringBoot(15500字)+Vue+毕业论文+指导搭建视频
  • 23种设计模式 - 适配器模式
  • CES Asia 2025“传播势能放大器”:科技与环保的双重盛宴
  • 9.PG数据库层权限管理(pg系列课程)第2遍
  • 【HBase】HBaseJMX 接口监控信息实现钉钉告警
  • 代理和NAT多路转接
  • 3.7大模型开发环境搭建:从单卡到分布式集群的全栈指南
  • Maven Repository 与 Artifactory 使用
  • QT6开发高性能企业视频会议-7 Linux中文输入法的支持
  • openEuler-24.03-LTS/virtual_machine_img 版本的安装
  • STM32完全学习——RT-thread标准版移植
  • Ubuntu学习备忘
  • Mybatis高级(动态SQL)
  • Stream流简单使用