widoczny Aktualizacje na dole (4/30/2015)iOS wykresy Jak unieważnić/przerysować po ustawieniu dane
Jestem wykonawczych wykresu kołowego w Swift dla iOS iOS z wykorzystaniem wykresów i wybrali aby dostosować legendę. Warto zauważyć, że wykres jest wyświetlany w komórce z UICollectionView. Problem polega na tym, że na pierwszym wyświetleniu zawartość niestandardowej legendy nie jest wyświetlana. Zamiast tego otrzymuję treść legendy wygenerowaną z danych.
Po przewinięciu widoku poza ekranem, a następnie przewinięciu go z powrotem na ekran, wyświetlana jest odpowiednia niestandardowa legenda. Tak więc jestem zgadując, że muszę wymusić przerysowanie/przekaz/ponowne coś po ustawieniu mojej niestandardowej legendy. Nie wiem, jak to zrobić. Czy ktoś ma pomysł? Czy całkowicie mi czegoś brakuje? Dzięki!
Wykres na ekranie początkowym - dane generowane (źle) legenda
Wykres po przewinięciu off i powrót na ekran - (właściwa legenda)
Oto mój kod rysowanie tego wykresu:
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)
}
Aktualizacja 4/30/2015
Na podstawie dyskusji z autorem MPAndroidChart (na którym opiera się iOS wykresy), wydaje się, że nie ma sensu w cyklu wyświetlania wykresu, gdzie można zastąpić legendę o „pierwszy rysować". Zasadniczo wykres jest renderowany, gdy jest tworzony, bez względu na wszystko. Jeśli ustawisz dane na wykresie, wykres użyje tych danych do utworzenia legendy, a następnie wyświetli. Nie można zmienić legendy między punktem nastawiania danych a punktem renderowania wykresu.
setNeedsDisplay()
potencjalnie może odczekać na wykresie, aby uczynić zaktualizować legendy, a następnie wywołać chart.setNeedsDisplay() sygnalizuje wykres odświeżenia. Niestety, jest z tym problem z synchronizacją. Jeśli wywołasz tę metodę natychmiast po renderowaniu wykresu, nie uruchamia się lub (bardziej prawdopodobne) wystrzeliwuje zbyt szybko i jest skutecznie ignorowana. W moim kodzie umieszczenie tego wywołania w viewDidLoad lub viewDidAppear nie przyniosło żadnego efektu. Jednak ...
Tworzenie tego samego wykresu w Javie dla systemu Android (przy użyciu MPAndroidChart) powoduje ten sam problem. Po trochę pogawędek, zauważyłem, że jeśli zadzwoniłem do chart.invalidate() po opóźnieniu (używając Handler.postDelayed()), to wystrzeliłoby poprawnie. Okazuje się, że podobne podejście działa w przypadku ios-chartów na iOS.
Jeśli ktoś używa GCD do opóźnienia wywołania setNeedsDisplay(), nawet na kilka milisekund po renderowaniu, wydaje się, że to wystarczy. Dodałem następujący kod natychmiast po uruchomieniu widoku wykresu w moim ViewController („komórki” to UICollectionViewCell zawierający widok wykresu):
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()
}
Korzystanie awesome „opóźnienie” metodę z tym SO post: https://stackoverflow.com/a/24318861
Oczywiście, jest to paskudny hack, ale wydaje się, że to wystarczy. Nie jestem pewien, czy podoba mi się pomysł wykorzystania tego hacka w produkcji.
Dla każdego Android ludzi, którzy obrażają się na tym stanowisku:
Poniższy kod daje ten sam efekt przy użyciu 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);
Czy chciał tylko dodać pieChart.setNeedsDisplay() na końcu metody viewDidLoad()? –
@Shawn Tak, spróbowałem (z wielu punktów w kodzie), ale bez radości. Cykl życia wykresu w bibliotece MPAndroidCharts, na którym jest oparty, renderuje wykres na widoku init i kiedy dane są ustawione. Rozwiązanie przez chart.invalidate() (po opóźnieniu), ale ta metoda nie znajduje się w porcie ios-chart. Nie ma jeszcze rozwiązania, ale spróbuję jeszcze kilku rzeczy i zaktualizuję pytanie, czego się dowiem. – MojoTosh