MPAndroidChart BarChart не учитывает ширину полосы при перерисовке - PullRequest
0 голосов
/ 18 мая 2018

Я использую BarChart в приложении, но иногда, когда я перерисовываю его, ширина полос не учитывается, и я получаю противоречивые результаты (даже если количество значений по оси X всегда равно 100).

Вот как я хочу, чтобы он выглядел всегда:

enter image description here

но иногда это выглядит так:

enter image description here

enter image description here

Кто-нибудь знает, почему это происходит и как я могу заставить его всегда выглядеть одинаково?

Я думаю, что это как-то связано с диапазоном значений по оси X, поскольку диаграмма выглядит хорошо, когда диапазон изменяется от 0 до 50 или около того, но выглядит плохо, когда диапазон меньше.

Я уже настраиваю значение ширины бара следующим образом, но это не помогает:

barChartView?.data?.barWidth = 0.3f

Это полная конфигурация графика, которую я использую (этот метод запускается только один раз, когда Fragment):

private fun setUpChartView() {
    barChartView?.setTouchEnabled(false)

    val xAxis = barChartView?.xAxis
    val yAxis = barChartView?.axisLeft

    // Hide all parts of the chart that we don't want to show
    barChartView?.legend?.isEnabled = false
    barChartView?.description?.isEnabled = false
    barChartView?.setDrawGridBackground(false)
    xAxis?.setDrawGridLines(false)
    xAxis?.setDrawAxisLine(false)
    yAxis?.setDrawAxisLine(false)
    barChartView?.axisRight?.isEnabled = false

    // Show the Y axis grid lines as dashed
    yAxis?.enableGridDashedLine(5f, 10f, 0f)

    val barChartTextColor = getColor(R.color.chart_text)
    val barChartTextSize = 12f
    val barChartLabelsTypeface = Typeface.SANS_SERIF

    // Show the X axis labels at the bottom and set the proper style
    xAxis?.position = XAxis.XAxisPosition.BOTTOM
    xAxis?.textColor = barChartTextColor
    xAxis?.textSize = barChartTextSize
    xAxis?.typeface = barChartLabelsTypeface

    // Set the proper style for the Y axis labels
    yAxis?.textSize = barChartTextSize
    yAxis?.textColor = barChartTextColor
    yAxis?.typeface = barChartLabelsTypeface

    barChartView?.setNoDataText("")

    val viewPortHandler = barChartView?.viewPortHandler
    val axisTransformer = barChartView?.getTransformer(LEFT)

    // Set a custom axises so that we can control the drawing of the labels and grid lines
    barChartView?.setXAxisRenderer(CustomEntriesXAxisRenderer(viewPortHandler = viewPortHandler,
                                                                 xAxis = xAxis,
                                                                 transformer = axisTransformer))
    barChartView?.rendererLeftYAxis = CustomEntriesYAxisRenderer(viewPortHandler = viewPortHandler,
                                                                    yAxis = yAxis,
                                                                    transformer = axisTransformer)
}

Это код, который я использую для рисования диаграммы при получении новых данных:

private fun drawBarChart() {
    // The data list has always 100 items
    val entries = data.map { BarEntry(it.x, it.y) }

    // Prepare the chart data set by adding the entries and configuring its style (colors, etc.)
    val dataSet = BarDataSet(entries, null)
    dataSet.setDrawValues(false)
    dataSet.colors = colorsList

    // Load data to chart
    if (barChartView?.data == null) {
        // If there is no data set yet, create a new data object and add it to the chart (this happens the first
        // time we draw the chart after the Fragment was created, or after an empty data list was returned)
        barChartView?.data = BarData(dataSet)
    } else {
        // If there is already data in the chart, remove the existing data set and add the new one
        barChartView.data?.removeDataSet(0)
        barChartView.data?.addDataSet(dataSet)

        barChartView.notifyDataSetChanged()
    }

    // Set a custom width for the bars or the chart will draw them too wide
    barChartView?.data?.barWidth = 0.3f

    val xAxis = barChartView?.xAxis
    val yAxis = barChartView?.axisLeft

    // Set the min and max values for the Y axis or the chart lib will calculate them and add more values than
    // we need
    yAxis?.axisMinimum = 0f
    yAxis?.axisMaximum = entries.last().y

    // Set the entries that need to be drawn in the X axis, so the chart doesn't calculate them automatically
    (barChartView?.rendererXAxis as CustomEntriesXAxisRenderer).entries = xAxisEntries

    // Set the entries that need to be drawn in the Y axis, so the chart doesn't calculate them automatically
    (barChartView?.rendererLeftYAxis as CustomEntriesYAxisRenderer).entries = yAxisEntries

    // Add the label count to avoid the chart from automatically setting a range of labels instead of the ones we need,
    // which prevents the axis value formatter below to set the correct labels
    xAxis?.setLabelCount(xAxisEntries.size, true)
    yAxis?.setLabelCount(yAxisEntries.size, true)

    // Use a custom value formatter that sets only the needed labels on the axises
    xAxis?.setValueFormatter { value, _ ->
        // TODO
    }
    yAxis?.setValueFormatter { value, _ ->
        // TODO
    }

    // Draw chart
    barChartView?.invalidate()
}

И это инструментПримечание о созданных мной пользовательских средствах визуализации осей:

class CustomEntriesXAxisRenderer(viewPortHandler: ViewPortHandler?, xAxis: XAxis?, transformer: Transformer?)
    : XAxisRenderer(viewPortHandler, xAxis, transformer) {

    /**
     * Entries used to draw the grid lines and labels on the X axis.
     */
    var entries: List<Float>? = null


    override fun computeSize() {
        entries?.forEachIndexed { i, value ->
            mAxis.mEntries[i] = value
        }

        super.computeSize()
    }

}

class CustomEntriesYAxisRenderer(viewPortHandler: ViewPortHandler?, yAxis: YAxis?, transformer: Transformer?)
    : YAxisRenderer(viewPortHandler, yAxis, transformer) {

    /**
     * Entries used to draw the grid lines and labels on the Y axis.
     */
    var entries: List<Float>? = null


    override fun computeAxisValues(min: Float, max: Float) {
        super.computeAxisValues(min, max)

        entries?.forEachIndexed { i, value ->
            mAxis.mEntries[i] = value
        }
    }

}

1 Ответ

0 голосов
/ 20 мая 2018

Один из разработчиков MPAndroidChart сказал, что это действительно ошибка в библиотеке, и теперь она находится в их списке дел.Если у кого-то возникла эта проблема, вы можете следить за прогрессом здесь .

Тем временем, поэкспериментировав с этим некоторое время, я обнаружил (довольно уродливый) хак, который мешает графикувыглядит слишком плохо:

barChartView?.data?.barWidth = when (entries.last().x) {
    in 0..30 -> 0.1f
    in 30..60 -> 0.2f
    else -> 0.3f
}

Вы можете настроить значения в соответствии с тем, что выглядит хорошо для ваших записей данных, но в основном, установив другую ширину полосы в зависимости от диапазона значений X в наборе данных, вы можете по крайней мересделайте это немного лучше, пока ошибка не будет исправлена.

...