ios-charts设置数据后如何使无效/重绘

时间:2015-04-30 00:38:30

标签: mpandroidchart ios-charts

请参阅底部更新(2015年4月30日)

我使用ios-charts在Swift for iOS中实现饼图,并选择自定义图例。值得注意的是,图表显示在UICollectionView的单元格中。问题是,在第一次显示时,不显示自定义图例内容。相反,我获得了从数据生成的图例内容。

如果我在屏幕外滚动视图,然后将其滚动回屏幕,则会显示正确的自定义图例。所以,我强烈猜测在设置自定义图例后我需要强制重绘/重新布局/重新设置。我还没弄明白怎么做。有没有人有想法?我完全错过了什么吗?谢谢!

初始显示图表 - 数据生成(错误)图例 Chart on initial display - generated legend

滚动关闭并返回到屏幕后的

图表 - (正确的图例) Chart with proper legend

这是我绘制此图表的代码:

func initChart(pieChart: PieChartView) {
    numFormatter.maximumFractionDigits = 0

    pieChart.backgroundColor = UIColor.whiteColor()

    pieChart.usePercentValuesEnabled = false
    pieChart.drawHoleEnabled = true
    pieChart.holeTransparent = true
    pieChart.descriptionText = ""
    pieChart.centerText = "30%\nComplete"

    pieChart.data = getMyData()

    // Setting custom legend info, called AFTER setting data
    pieChart.legend.position = ChartLegend.ChartLegendPosition.LeftOfChartCenter
    pieChart.legend.colors = [clrGreenDk, clrGold, clrBlue]
    pieChart.legend.labels = ["Complete","Enrolled","Future"]
    pieChart.legend.enabled = true
}

func getMyData() -> ChartData {

    var xVals = ["Q201","R202","S203","T204","U205", "V206"]

    var courses: [ChartDataEntry] = []
    courses.append(ChartDataEntry(value: 3, xIndex: 0))
    courses.append(ChartDataEntry(value: 3, xIndex: 1))
    courses.append(ChartDataEntry(value: 4, xIndex: 2))
    courses.append(ChartDataEntry(value: 4, xIndex: 3))
    courses.append(ChartDataEntry(value: 3, xIndex: 4))
    courses.append(ChartDataEntry(value: 3, xIndex: 5))

    let dsColors = [clrGreenDk, clrGreenDk, clrBlue, clrBlue, clrGold, clrGold]

    let pcds = PieChartDataSet(yVals: courses, label: "")
    pcds.sliceSpace = CGFloat(4)
    pcds.colors = dsColors
    pcds.valueFont = labelFont!
    pcds.valueFormatter = numFormatter
    pcds.valueTextColor = UIColor.whiteColor()

    return ChartData(xVals: xVals, dataSet: pcds)
}

2015年4月30日更新

根据与MPAndroidChart(ios-charts所基于的)作者的讨论,看来图表显示生命周期中没有一个点可以覆盖"首先绘制"的图例。基本上,无论如何,图表都会在创建时呈现。如果在图表上设置数据,图表将使用该数据创建图例,然后进行渲染。无法更改设置数据点和图表渲染点之间的图例。

setNeedsDisplay()

潜在地,可以等待图表渲染,更新图例,然后调用chart.setNeedsDisplay()以指示图表重绘。可悲的是,这有一个时间问题。如果您在渲染图表后立即调用此方法,则它不会触发或(更有可能)它过早触发并被有效忽略。在我的代码中,将此调用放在viewDidLoad或viewDidAppear中无效。然而...

在Java for Android中构建相同的图表(使用MPAndroidChart)会导致同样的问题。在搞砸了一下之后,我注意到如果我在延迟(使用Handler.postDelayed())之后调用了chart.invalidate(),它会正确触发。事实证明,类似的方法适用于iOS上的ios-charts。

如果使用GCD延迟对setNeedsDisplay()的调用,即使在渲染后几毫秒,它似乎也可以解决问题。在我的ViewController初始化图表视图后,我立即添加了以下代码(" cell"是包含图表视图的UICollectionViewCell):

delay(0.05) {
    cell.pieChartView.legend.colors = [self.clrGreenDk, self.clrGold, self.clrBlue]
    cell.pieChartView.legend.labels = ["Complete","Enrolled","Future"]
    // Re-calc legend dimensions for proper position (Added 5/2/2015)
    cell.pieChartView.legend.calculateDimensions(cell.pieChartView.labelFont!)
    cell.pieChartView.setNeedsDisplay()
}

使用令人敬畏的"延迟"来自此SO帖子的方法:https://stackoverflow.com/a/24318861

显然,这是一个讨厌的黑客,但它似乎做了伎俩。我不确定我是否喜欢在生产中使用这种黑客的想法。

对于任何偶然发现此帖子的Android用户:

以下代码使用MPAndroidChart实现相同的效果:

    // Inside onCreate()
    pie = (PieChart) findViewById(R.id.chart1);
    configPieChart(pie);

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            String[] legLabels = new String[]{"Complete","Enrolled","Future"};
            ArrayList<Integer> legColors = new ArrayList<Integer>();
            legColors.add(blue);
            legColors.add(gold);
            legColors.add(green);

            pie.getLegend().setPosition(Legend.LegendPosition.LEFT_OF_CHART_CENTER);
            pie.getLegend().setColors(legColors);
            pie.getLegend().setLabels(legLabels);

            pie.invalidate();
        }
    }, 20);

1 个答案:

答案 0 :(得分:7)

我是ios-charts的作者,我们正在开发自定义图例数据的功能,而不是那些“黑客”。

在ios-charts的最新提交中,您已经可以看到为图例添加额外行的extraLabelsextraColors属性,以及允许您设置的setLegend函数完全自定义数据。

这也将很快添加到Android版本中。

享受: - )