iOS Charts, настройка меток данных - PullRequest
0 голосов
/ 20 октября 2018

Я работаю с библиотекой диаграмм Даниельгинди с моим приложением для iOS.На этой диаграмме я отображаю данные диаграммы, используя lineChartDataSet.drawValuesEnabled = true.Я хочу отображать значения (точки данных) вертикально, а не горизонтально.Может кто-нибудь сказать, пожалуйста, как изменить отображение данных?

1 Ответ

0 голосов
/ 21 октября 2018

Создайте пользовательский рендер, унаследованный от LineChartRenderer.В этом рендере вам нужно перезаписать одну функцию - drawValues(context: CGContext).Фактически, вы можете скопировать и вставить большую часть исходного кода для этой функции из базового класса, вам нужно только изменить функцию ChartUtils.drawText в варианте с параметром поворота текста.К счастью, класс ChartUtils имеет такую ​​функцию.Кроме того, добавьте новый инициализатор и переопределите функцию shouldDrawValues, поскольку она недоступна из-за уровня доступа internal в базовом классе.

import Foundation
import Charts

open class LineChartRendererWithVerticalValues: LineChartRenderer
{

    var _xBounds = XBounds() // Reusable XBounds object

    init(view: LineChartView) {
        super.init(dataProvider: view, animator: view.chartAnimator, viewPortHandler: view.viewPortHandler)
    }

    // Redefine `shouldDrawValues` function because of `internal` access level in the base class
    func shouldDrawValues(forDataSet set: IChartDataSet) -> Bool
    {
        return set.isVisible && (set.isDrawValuesEnabled || set.isDrawIconsEnabled)
    }

    // Keep all source code from the base class, except using another version of `ChartUtils.drawText` function
    open override func drawValues(context: CGContext)
    {
        guard
            let dataProvider = dataProvider,
            let lineData = dataProvider.lineData
            else { return }

        if isDrawingValuesAllowed(dataProvider: dataProvider)
        {
            var dataSets = lineData.dataSets

            let phaseY = animator.phaseY

            var pt = CGPoint()

            for i in 0 ..< dataSets.count
            {
                guard let dataSet = dataSets[i] as? ILineChartDataSet else { continue }

                if !shouldDrawValues(forDataSet: dataSet)
                {
                    continue
                }

                let valueFont = dataSet.valueFont

                guard let formatter = dataSet.valueFormatter else { continue }

                let trans = dataProvider.getTransformer(forAxis: dataSet.axisDependency)
                let valueToPixelMatrix = trans.valueToPixelMatrix

                let iconsOffset = dataSet.iconsOffset

                var valOffset = Int(dataSet.circleRadius * 1.75)

                if !dataSet.isDrawCirclesEnabled
                {
                    valOffset = valOffset / 2
                }

                _xBounds.set(chart: dataProvider, dataSet: dataSet, animator: animator)

                for j in stride(from: _xBounds.min, through: min(_xBounds.min + _xBounds.range, _xBounds.max), by: 1)
                {
                    guard let e = dataSet.entryForIndex(j) else { break }

                    pt.x = CGFloat(e.x)
                    pt.y = CGFloat(e.y * phaseY)
                    pt = pt.applying(valueToPixelMatrix)

                    if (!viewPortHandler.isInBoundsRight(pt.x))
                    {
                        break
                    }

                    if (!viewPortHandler.isInBoundsLeft(pt.x) || !viewPortHandler.isInBoundsY(pt.y))
                    {
                        continue
                    }

                    if dataSet.isDrawValuesEnabled {

                        // Changes are here!
                        // Draw text with rotation
                        ChartUtils.drawText(
                            context: context,
                            text: formatter.stringForValue(
                                e.y,
                                entry: e,
                                dataSetIndex: i,
                                viewPortHandler: viewPortHandler),
                            point: CGPoint(
                                x: pt.x,
                                y: pt.y - CGFloat(valOffset) - valueFont.lineHeight),
                            attributes: [NSAttributedStringKey.font: valueFont, NSAttributedStringKey.foregroundColor: dataSet.valueTextColorAt(j)],
                            anchor: CGPoint(x: 0.5, y: 0.5),
                            angleRadians:CGFloat.pi*3.0/2.0)
                    }

                    if let icon = e.icon, dataSet.isDrawIconsEnabled
                    {
                        ChartUtils.drawImage(context: context,
                                             image: icon,
                                             x: pt.x + iconsOffset.x,
                                             y: pt.y + iconsOffset.y,
                                             size: icon.size)
                    }
                }
            }
        }
    }
}

Используйте пользовательский рендерер для LineChartView и добавьте дополнительное смещение, если вертикальноезначения не вписываются в представление.

myLineChartView.renderer = LineChartRendererWithVerticalValues(view: lineChartView)
myLineChartView.extraTopOffset = 20

LineChartView with vertical data labels

...