Okay, so after some tinkering with the Y axis renderer I managed to achieve this look and behaviour.
So in order to get that look you would have to:
- Disable the default limit line label by calling
setDrawLabelsEnabled()
with the parameter set to false
- Make changes to the YAxisRenderer.swift. The key is to slightly redo the
internal func drawYLabels(...)
to draw additional labels for each limit line. See the code below.
Add the offsets to the X and Y axes (both of them) like this:
chart.leftAxis.xOffset = 10.0
chart.leftAxis.yOffset = 0.0
Here's a code snippet of the new internal func drawYLabels(...)
method:
internal func drawYLabels(
context: CGContext,
fixedPosition: CGFloat,
positions: [CGPoint],
offset: CGFloat,
textAlign: NSTextAlignment)
{
guard
let yAxis = self.axis as? YAxis
else { return }
let labelFont = yAxis.labelFont
let labelTextColor = yAxis.labelTextColor
let from = yAxis.isDrawBottomYLabelEntryEnabled ? 0 : 1
let to = yAxis.isDrawTopYLabelEntryEnabled ? yAxis.entryCount : (yAxis.entryCount - 1)
for i in stride(from: from, to: to, by: 1)
{
let text = yAxis.getFormattedLabel(i)
ChartUtils.drawText(
context: context,
text: " " + text + " ", // Adding some spaces infront and after the label to make some additional space for the bigger "limit line" labels
point: CGPoint(x: fixedPosition, y: positions[i].y + offset),
align: textAlign,
attributes: [NSAttributedString.Key.font: labelFont, NSAttributedString.Key.foregroundColor: labelTextColor])
}
// This is where we start to draw labels for limit lines
let myTransformer = self.transformer
for line in yAxis.limitLines {
let point = myTransformer!.pixelForValues(x: 0.0, y: line.limit)
let text = (" " + line.label + " ") as NSString // Adding some spaces to the label in order to make some additional space for the label
let size = text.size(withAttributes: [NSAttributedString.Key.font: labelFont, NSAttributedString.Key.foregroundColor: UIColor.darkGray, NSAttributedString.Key.backgroundColor: UIColor.green])
var labelPoint: CGPoint?
// Drawing the triangle in front of the custom label
let trianglePath = UIBezierPath()
if yAxis.axisDependency == .right {
labelPoint = CGPoint(x: fixedPosition + (size.height * 0.3), y: point.y - (size.height / 2))
if textAlign == .center
{
labelPoint!.x -= size.width / 2.0
}
else if textAlign == .right
{
labelPoint!.x -= size.width
}
trianglePath.move(to: CGPoint(x: labelPoint!.x - size.height * 0.375, y: labelPoint!.y + (size.height / 2)))
trianglePath.addLine(to: CGPoint(x: labelPoint!.x, y: labelPoint!.y + (size.height * 0.78)))
trianglePath.addLine(to: CGPoint(x: labelPoint!.x, y: labelPoint!.y + (size.height * 0.22)))
} else {
labelPoint = CGPoint(x: 0.0, y: point.y - (size.height / 2))
trianglePath.move(to: CGPoint(x: labelPoint!.x + size.width * 1.175, y: labelPoint!.y + (size.height / 2)))
trianglePath.addLine(to: CGPoint(x: labelPoint!.x + size.width, y: labelPoint!.y + (size.height * 0.78)))
trianglePath.addLine(to: CGPoint(x: labelPoint!.x + size.width, y: labelPoint!.y + (size.height * 0.22)))
}
NSUIGraphicsPushContext(context)
// Drawing the custom label itself
(text as NSString).draw(at: labelPoint!, withAttributes: [NSAttributedString.Key.font: labelFont, NSAttributedString.Key.foregroundColor: UIColor.darkGray, NSAttributedString.Key.backgroundColor: UIColor.green])
trianglePath.close()
// Drawing the triangle with the same color as the limit line and it's label
line.lineColor.setFill()
trianglePath.fill()
NSUIGraphicsPopContext()
}
}
The final result looks like this: screenshot
This implementation is not the cleanest one but at least it worked for me.
Feel free to ask questions if something was unclear in my words.