2015-04-30 5 views
6

vedere gli aggiornamenti in basso (4/30/2015)iOS classifiche Come invalidare/ridisegnare dopo aver impostato i dati

Sto implementando un grafico a torta a Swift per iOS che utilizzano iOS classifiche, e hanno scelto per personalizzare la legenda. Di nota, il grafico viene visualizzato all'interno di una cella di UICollectionView. Il problema è che al primo display, il contenuto della legenda personalizzata non viene visualizzato. Invece, ottengo il contenuto delle leggende generato dai dati.

Se si scorre la vista fuori dallo schermo, quindi lo si scorre indietro sullo schermo, viene visualizzata la legenda personalizzata corretta. Quindi, sono supposto che io debba forzare un ridisegno/relayout/re-qualcosa dopo aver impostato la mia legenda personalizzata. Non ho capito come farlo. Qualcuno ha un'idea? Mi manca qualcosa? Grazie!

Grafico sulla schermata iniziale - i dati generati (sbagliato) leggenda Chart on initial display - generated legend

Grafico dopo lo scorrimento fuori e indietro sullo schermo - (corretta leggenda) Chart with proper legend

Ecco il mio codice per disegno questo schema:

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) 
} 

Aggiornamento 4/30/2015

Sulla base di discussione con l'autore di MPAndroidChart (su cui si basa ios-grafici), sembra non c'è un punto del ciclo di vita del display grafico dove si può ignorare la leggenda sulla "prima disegnare". Fondamentalmente, il grafico è reso quando viene creato, non importa quale. Se si impostano i dati sul grafico, il grafico utilizza tali dati per creare la legenda e quindi esegue il rendering. Non è possibile modificare la legenda tra il punto di impostazione dei dati e il punto di rendering del grafico.

setNeedsDisplay()

Potenzialmente, si può aspettare che il grafico di rendering, aggiornare la legenda, e quindi chiamare chart.setNeedsDisplay() per segnalare la tabella per ridisegnare. Purtroppo, c'è un problema di temporizzazione con questo. Se si chiama questo metodo immediatamente dopo aver eseguito il rendering del grafico, non viene attivato o (più probabilmente) viene attivato troppo presto e viene effettivamente ignorato. Nel mio codice, l'inserimento di questa chiamata in viewDidLoad o viewDidAppear non ha avuto alcun effetto. Tuttavia ...

Costruire lo stesso grafico in Java per Android (utilizzando MPAndroidChart) comporta lo stesso problema. Dopo aver fatto un po 'di casino, ho notato che se avessi chiamato il chart.invalidate() dopo un ritardo (usando Handler.postDelayed()), si sarebbe attivato correttamente. Risulta che un approccio simile funziona per ios-charts su iOS.

Se si utilizza GCD per ritardare la chiamata a setNeedsDisplay(), anche per pochi millisecondi dopo il rendering, sembra che faccia il trucco. Ho aggiunto il seguente codice subito dopo l'inizializzazione vista del grafico nel mio ViewController ("cella" è l'UICollectionViewCell che contiene la vista grafico):

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() 
} 

Utilizzando il metodo impressionante "ritardo" da questo SO messaggio: https://stackoverflow.com/a/24318861

Ovviamente, questo è un brutto scherzo, ma sembra fare il trucco. Non sono sicuro che mi piaccia l'idea di usare questo trucco nella produzione, però.

Per qualsiasi popolare Android che inciampano su questo post:

Il codice seguente ottiene lo stesso effetto usando 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); 
+2

Hai cercato di aggiungere solo pieChart.setNeedsDisplay() alla fine del metodo viewDidLoad()? –

+0

@Shawn Sì, ho provato un po '(da molti punti nel codice), ma nessuna gioia. Il ciclo di vita della visualizzazione del grafico nella libreria MPAndroidCharts, su cui si basa questo, rende il grafico sulla vista init e quando i dati sono impostati. Risolvibile tramite chart.invalidate() (dopo il ritardo), ma questo metodo non si trova nella porta ios-chart. Nessuna soluzione ancora, ma proverò ancora un po 'di cose e aggiornerò la domanda con qualunque cosa io scopra. – MojoTosh

risposta

7

Io sono l'autore di ios-charts, e siamo lavorando su funzionalità per la personalizzazione dei dati delle legende, senza questi "hack".

Nell'ultimo impegna a IOS-grafici, si può già vedere extraLabels e extraColors proprietà che aggiungono linee extra alla leggenda, e una funzione di setLegend che permette di impostare un dati personalizzati del tutto.

Questo sarà presto aggiunto anche alla versione per Android.

Godetevi :-)

+0

tutte le notizie su questo problema? –

+0

Risolto molto tempo fa ... –

+0

@ daniel.gindi Fellow israeliano qui! Grazie per aver creato questa fantastica libreria! Potresti dare un'occhiata alla mia domanda per caso, per favore? http://stackoverflow.com/questions/43463040/show-only-last-n-bars-ios-charts – MarksCode