0

I'm creating a chart using Charts library to draw a combined chart in my app.

I succeeded in drawing the graph. Now I want to change the xAxis label text color of specific labels. The example was shown in the pic.enter image description here

As in the picture I want to change the color of specific values for example 03/06 & 06/06. When I referred the library on github they told me to override the drawValues() function to achieve this. As I'm newbie to swift programming I don't know how to achieve this. Please guide me on how to achieve this task. Thanks in advance.

Umair Afzal
  • 4,947
  • 5
  • 25
  • 50
Praveen Kumar
  • 547
  • 1
  • 7
  • 33

3 Answers3

2

Inside the XAxisRenderer.swift (not the XAxisRendererHorizontalBarChart like the other answer suggested) add this list with your colors above the drawLabels function:

 let labelTextColorList = [UIColor.black, UIColor.red, UIColor.blue, UIColor.brown, UIColor.cyan, UIColor.black, UIColor.black, UIColor.black, UIColor.black, UIColor.black, UIColor.black, UIColor.black]

then replace the drawLabels function with this code:

 /// draws the x-labels on the specified y-position
open func drawLabels(context: CGContext, pos: CGFloat, anchor: CGPoint)
{
    guard
        let xAxis = self.axis as? XAxis,
        let viewPortHandler = self.viewPortHandler,
        let transformer = self.transformer
        else { return }

    #if os(OSX)
        let paraStyle = NSParagraphStyle.default().mutableCopy() as! NSMutableParagraphStyle
    #else
        let paraStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
    #endif
    paraStyle.alignment = .center

    //label attrs moved from here
    /*            let labelAttrs = [NSFontAttributeName: xAxis.labelFont,
     NSForegroundColorAttributeName: xAxis.labelTextColor,
     NSParagraphStyleAttributeName: paraStyle] as [String : NSObject]
     */

    let labelRotationAngleRadians = xAxis.labelRotationAngle * ChartUtils.Math.FDEG2RAD

    let centeringEnabled = xAxis.isCenterAxisLabelsEnabled

    let valueToPixelMatrix = transformer.valueToPixelMatrix

    var position = CGPoint(x: 0.0, y: 0.0)

    var labelMaxSize = CGSize()

    if xAxis.isWordWrapEnabled
    {
        labelMaxSize.width = xAxis.wordWrapWidthPercent * valueToPixelMatrix.a
    }

    let entries = xAxis.entries

    for i in stride(from: 0, to: entries.count, by: 1)
    {

        //label attrs moved to here
        let labelAttrs: [String: NSObject]!

        if(i<labelTextColorList.count) {
            labelAttrs = [NSFontAttributeName: xAxis.labelFont,
                                  NSForegroundColorAttributeName: labelTextColorList[i],
                                  NSParagraphStyleAttributeName: paraStyle] as [String : NSObject]
        }
        else {
            labelAttrs = [NSFontAttributeName: xAxis.labelFont,
                          NSForegroundColorAttributeName: xAxis.labelTextColor,
                          NSParagraphStyleAttributeName: paraStyle] as [String : NSObject]

        }
        if centeringEnabled
        {
            position.x = CGFloat(xAxis.centeredEntries[i])
        }
        else
        {
            position.x = CGFloat(entries[i])
        }

        position.y = 0.0
        position = position.applying(valueToPixelMatrix)

        if viewPortHandler.isInBoundsX(position.x)
        {
            let label = xAxis.valueFormatter?.stringForValue(xAxis.entries[i], axis: xAxis) ?? ""

            let labelns = label as NSString

            if xAxis.isAvoidFirstLastClippingEnabled
            {
                // avoid clipping of the last
                if i == xAxis.entryCount - 1 && xAxis.entryCount > 1
                {
                    let width = labelns.boundingRect(with: labelMaxSize, options: .usesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width

                    if width > viewPortHandler.offsetRight * 2.0
                        && position.x + width > viewPortHandler.chartWidth
                    {
                        position.x -= width / 2.0
                    }
                }
                else if i == 0
                { // avoid clipping of the first
                    let width = labelns.boundingRect(with: labelMaxSize, options: .usesLineFragmentOrigin, attributes: labelAttrs, context: nil).size.width
                    position.x += width / 2.0
                }
            }

            drawLabel(context: context,
                      formattedLabel: label,
                      x: position.x,
                      y: pos,
                      attributes: labelAttrs,
                      constrainedToSize: labelMaxSize,
                      anchor: anchor,
                      angleRadians: labelRotationAngleRadians)
        }
    }
}

result: enter image description here

DevB2F
  • 4,674
  • 4
  • 36
  • 60
1

there is below method in XAxisRendererHorizontalBarChart.swift file of charts library. It will set the text for xAxis. You can customize it according to your use case.

open override func drawLabels(context: CGContext, pos: CGFloat, anchor: CGPoint)
DP's
  • 209
  • 1
  • 4
0

How I did this was that I calculated the width of xAxis and then found the distance between labels to add between labels

let dateAr = ["3개월 전","2개월 전","1개월 전","현재","1개월 후"] // array,i want to add
let xAixsLabelView = UIView() // view, it will contain labels beneath
let xAxisLabelList = [UILabel(),UILabel(),UILabel(),UILabel(),UILabel()] // array, I will add

.....


func drawXLabel(){
    let color1 = UIColor(red: 0.875, green: 0.875, blue: 0.875, alpha: 1)
    let color2 = BaseViewController().hexStringToUIColor(hex: "#3246FA")

    xAixsLabelView.backgroundColor = .clear
    xAixsLabelView.frame = CGRect(x: lineChartView.frame.minX + 13, y: lineChartView.frame.maxY - 30, width: lineChartView.frame.width , height: 50)
    
    let chartViewWidth = lineChartView.frame.width
    let labelWidth = lineChartView.xAxis.labelWidth
    let paddingWidth = CGFloat((chartViewWidth - (labelWidth * 5))/6) // 5 is the number of labels, and 6 is the number of padding that wraps labels( you need to add 1 to the number of labels 
    
    for i in 0...4{
        
        var padding = paddingWidth * CGFloat(Double(i) + 0.95) + labelWidth * CGFloat(i)
        if i == 0 {
            xAxisLabelList[i].text = "3개월 전"
            xAxisLabelList[i].textColor = color1
            padding = paddingWidth * 1
        }else if i == 1{
            xAxisLabelList[i].text = "2개월 전"
            xAxisLabelList[i].textColor = color1
        }else if i == 2{
            xAxisLabelList[i].text = "1개월 전"
            xAxisLabelList[i].textColor = color1
        }else if i == 3{
            xAxisLabelList[i].text = "현재"
            xAxisLabelList[i].textColor = color2
        }else if i == 4{
            xAxisLabelList[i].text = "1개월 후"
            xAxisLabelList[i].textColor = color1
            padding = paddingWidth * CGFloat(4.7) + labelWidth * CGFloat(i)
        }
                    
        xAxisLabelList[i].font = UIFont(name: "PretendardVariable-Medium", size: 10)
        xAxisLabelList[i].frame = CGRect(x:padding , y:10 , width: labelWidth, height: 18)
       
        
        xAixsLabelView.addSubview(xAxisLabelList[i])
    }
    
    chartView.addSubview(xAixsLabelView)
    chartView.bringSubviewToFront(xAixsLabelView)
    
}

make sure these

  • what you are gonna do is add View on lineChartView not change xAxis on linechartview
  • all charts are different so make sure your offsets and parentView width differences
  • the list that you are gonna add must just the same in xAxis (length, text)
  • make sure color .clear in xAxis labelColor
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Lhu
  • 1
  • 1