Создайте пользовательский рендер, унаследованный от 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