ios-charts Как сделать недействительным / перерисовать после установки данных
См. Обновления в нижней части (30.04.2015)
Я внедряю круговую диаграмму в Swift для iOS, используя ios-диаграммы, и решил настроить легенду. Следует отметить, что диаграмма отображается в ячейке UICollectionView. Проблема в том, что при первом отображении содержимое пользовательской легенды не отображается. Вместо этого я получаю содержание легенды, сгенерированное из данных.
Если я прокручиваю вид за пределами экрана, а затем возвращаю его обратно на экран, отображается соответствующая пользовательская легенда. Итак, я предполагаю, что мне нужно вызвать перерисовку / ретрансляцию / что-то новое после установки моей пользовательской легенды. Я не понял, как это сделать. У кого-нибудь есть идея? Я что-то упустил полностью? Спасибо!
Диаграмма при первоначальном отображении - легенда, сформированная данными (неверная)
Диаграмма после прокрутки и обратно на экран - (правильная легенда)
Вот мой код для рисования этой диаграммы:
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)
}
Обновление 30.04.2015
Основываясь на обсуждении с автором MPAndroidChart (на котором основаны ios-диаграммы), оказалось, что в жизненном цикле отображения диаграммы нет точки, где можно было бы переопределить легенду при "первом рисовании". По сути, диаграмма отображается при ее создании, несмотря ни на что. Если вы устанавливаете данные на диаграмме, диаграмма использует эти данные для создания легенды, а затем выполняет рендеринг. Невозможно изменить легенду между точкой задания данных и точкой рендеринга диаграммы.
setNeedsDisplay ()
Потенциально можно дождаться отображения диаграммы, обновить легенду, а затем вызвать chart.setNeedsDisplay(), чтобы подать сигнал на перерисовку диаграммы. К сожалению, есть проблема времени с этим. Если вы вызываете этот метод сразу после рендеринга диаграммы, он либо не срабатывает, либо (что более вероятно) срабатывает слишком рано и фактически игнорируется. В моем коде размещение этого вызова внутри viewDidLoad или viewDidAppear не имело никакого эффекта. Тем не мение...
Построение той же диаграммы в Java для Android (с использованием MPAndroidChart) приводит к той же проблеме. Немного поработав, я заметил, что если бы я вызвал chart.invalidate() после задержки (используя Handler.postDelayed()), он бы сработал правильно. Оказывается, аналогичный подход работает для ios-диаграмм на iOS.
Если кто-то использует GCD для задержки вызова setNeedsDisplay (), даже в течение нескольких миллисекунд после рендеринга, это, похоже, делает свое дело. Я добавил следующий код сразу после инициализации представления диаграммы в моем ViewController ("ячейка" - это 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: /questions/21142376/dispatchafter-gcd-v-byistrom/21142389#21142389
Очевидно, что это противный хак, но, похоже, он добился цели. Я не уверен, что мне нравится идея использовать этот хак в производстве.
Для любого пользователя 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 ответ
Я являюсь автором ios-диаграмм, и мы работаем над функциями для настройки данных легенды без этих "хаков".
В последних коммитах на ios-чартах вы уже можете видеть extraLabels
а также extraColors
свойства, которые добавляют дополнительные строки к легенде, и setLegend
функция, позволяющая полностью настроить пользовательские данные.
Это скоро будет добавлено и в версию для Android.
Наслаждаться:-)