ivnsch / SwiftCharts

Easy to use and highly customizable charts library for iOS
Apache License 2.0
2.53k stars 410 forks source link

Chart exceeds parent view #389

Closed robertschmid23 closed 5 years ago

robertschmid23 commented 5 years ago

I am trying to embed a chart into a view with a tab bar. If I add the Chart view to the main view of the UIController it used the space under the tab bar. So I added a subview constrained to the safe area and added the chart view to that. The chart view exceeds the bounds of that view. I've tried adding constraints with no effect. Eventually I shrunk my UIView enough that the Chart view at least stays within the visual area but I'd like to get better control than this.

My code follows. My settings are copied from ExamplesDefaults.swift since those seemed to be a stable starting point. (ChartDefaults) Here is the code;

(addChart() is called from viewDidLoad() )

`

func addChart()
{
    let xModel = getDateModel()
    let yModel = weightModel()

    let chartFrame = ChartDefaults.chartFrame(self.chartView!.bounds)

    let chartSettings = ChartDefaults.chartSettingsWithPanZoom

    // generate axes layers and calculate chart inner frame, based on the axis models
    let coordsSpace = ChartCoordsSpaceLeftBottomSingleAxis(chartSettings: chartSettings, chartFrame: chartFrame, xModel: xModel, yModel: yModel)
    let (xAxisLayer, yAxisLayer, innerFrame) = (coordsSpace.xAxisLayer, coordsSpace.yAxisLayer, coordsSpace.chartInnerFrame)

    let lineModel = ChartLineModel(chartPoints: weightLine(), lineColor: UIColor.red, lineWidth: 2, animDuration: 1, animDelay: 0)
    let chartPointsLineLayer = ChartPointsLineLayer(xAxis: xAxisLayer.axis, yAxis: yAxisLayer.axis, lineModels: [lineModel], pathGenerator: StraightLinePathGenerator()) // CatmullPathGenerator()) // || CubicLinePathGenerator

    let guideSettings = ChartGuideLinesDottedLayerSettings(linesColor: UIColor.black, linesWidth: ChartDefaults.guidelinesWidth)
    let guidelinesLayer = ChartGuideLinesDottedLayer(xAxisLayer: xAxisLayer, yAxisLayer: yAxisLayer, settings: guideSettings)

    let dividersSettings =  ChartDividersLayerSettings(linesColor: UIColor.black, linesWidth: ChartDefaults.guidelinesWidth, start: Env.iPad ? 7 : 3, end: 0)
    let dividersLayer = ChartDividersLayer(xAxisLayer: xAxisLayer, yAxisLayer: yAxisLayer, settings: dividersSettings)

    let chart = Chart(
        frame: chartFrame,
        innerFrame: innerFrame,
        settings: chartSettings,
        layers: [
            xAxisLayer,
            yAxisLayer,
            guidelinesLayer,
            dividersLayer,
            chartPointsLineLayer
        ]
    )

    self.chartView!.addSubview(chart.view)
    self.chartView!.layoutIfNeeded()
    self.chart = chart
}

func getDateModel() -> ChartAxisModel
{
    let dateGenerator = ChartAxisValuesGeneratorDate(unit: .day, preferredDividers: 2, minSpace: 1, maxTextSize: 12)
    let displayFormatter = DateFormatter()
    displayFormatter.dateFormat = "MMM dd"
    let dateLabels = ChartAxisLabelsGeneratorDate(labelSettings: ChartDefaults.labelSettings, formatter: displayFormatter)
    let dates = getDates()

    return ChartAxisModel(firstModelValue: dates.first!.scalar,
                                lastModelValue: dates.last!.scalar,
                                axisTitleLabels: [ChartAxisLabel(text: "Date", settings: ChartDefaults.labelSettings)],
                                axisValuesGenerator: dateGenerator,
                                labelsGenerator: dateLabels)

}

func weightModel() -> ChartAxisModel
{
    let weights = getWeights()
    let maxWeight = weights.max { $0.scalar < $1.scalar }
    let massGenerator = ChartAxisValuesGeneratorNice(minValue: 0, maxValue: maxWeight!.scalar * 1.5,
                                                     preferredDividers: 1, minSpace: 0, maxTextSize: 9)
    let massLabels = ChartAxisLabelsGeneratorNumber(labelSettings: ChartDefaults.labelSettings)

    return ChartAxisModel(firstModelValue: 0.0,
                                lastModelValue: weights.last!.scalar,
                                axisValuesGenerator: massGenerator,
                                labelsGenerator: massLabels)
}

func getDates() -> [ChartAxisValueDate]
{
    var dates:[ChartAxisValueDate] = []
    let displayFormatter = DateFormatter()
    displayFormatter.dateFormat = "MMM dd"

    if let entries = self.dailyEntries
    {
        for entry in entries
        {
            let cav = ChartAxisValueDate(date: entry.timeStamp, formatter: displayFormatter)

            dates.append(cav)
        }
    }
    return dates.sorted { $0.scalar < $1.scalar }
}

func getWeights() -> [ChartAxisValue]
{
    var weights:[ChartAxisValue] = []

    if let entries = self.dailyEntries
    {
        for entry in entries
        {
            weights.append(ChartAxisValue(scalar: entry.massKg))
        }
    }
    return weights.sorted { $0.scalar < $1.scalar }
}

func weightLine() -> [ChartPoint]
{
    var weightLine:[ChartPoint] = []
    let displayFormatter = DateFormatter()
    displayFormatter.dateFormat = "MMM dd"

    if let entries = self.dailyEntries
    {
        for entry in entries
        {
            weightLine.append(ChartPoint(x: ChartAxisValueDate(date: entry.timeStamp, formatter: displayFormatter),
                                         y: ChartAxisValue(scalar: entry.massKg)))
        }
    }
    return weightLine
}

`