2015-02-26 16 views
13

Ho creato un BarChart utilizzando MPAndroidChart e sto inserendo i dati dinamicamente. Ciò significa che ho bisogno anche del mio asse Y per essere determinato dinamicamente. Tutti i miei dati sono rappresentati come numeri interi, tuttavia l'asse Y a volte visualizza la legenda come valori decimali con 1 punto decimale.Force BarChart Le etichette dell'asse Y devono essere numeri interi?

Ho tentato di utilizzare un ValueFormatter per arrotondare i valori, ma il problema è che a volte i valori Y non sono in posizioni di valore intero (ad esempio 0,8,1,6,2,4, ecc.). Pertanto, se modifico solo questi in modo che siano interi, non saranno nella posizione corretta.

Esiste comunque la possibilità di forzare il BarChart a visualizzare solo valori in posizioni Integer? Va bene se salta un po ', anzi lo voglio quando i valori diventano grandi.

Modifica: quando ho detto che gli interi non sono nelle posizioni giuste, intendevo dire che una volta modificato ciò che ciascuna etichetta mostra non sono "corretti". Nel mio esempio ho 5 barre che mostrano i valori 3,4,2,3,2. La prima immagine è il 'default', il secondo è l'immagine una volta che ho modificato il formattatore valore utilizzando:

myBarChart.getYLabels().setFormatter(new ValueFormatter() 
{ 
    @Override 
    public String getFormattedValue(float v) 
    { 
     return ((int) v)+""; 
    } 
}); 

enter image description here enter image description here

Come si può vedere da queste immagini, i miei valori interi sono non dove dovrebbero essere (e ci sono due "2"). In questo esempio, tranne che per visualizzare i valori 0,1,2,3,4. Se ho molti più dati spero che sarebbe abbastanza intelligente per mostrare solo i valori per cui ho spazio, quindi per gli esempi se i dati contengono valori di 0-50 mostrerebbero qualcosa come 0,10,20,30 , 40,50 o eventualmente 0,15,30,45, ecc.

+0

avete risolto il problema? Voglio lo stesso cambiamento, puoi aiutarmi per favore? – AAnkit

+2

Non l'ho fatto, mi dispiace. Mi sono impegnato con altri progetti e ho appena finito di lasciarlo così com'è. Mi sono reso conto che per numeri interi più grandi questo problema non si presenta, ma al momento non c'è modo di farlo funzionare per i piccoli int. – Fozefy

+0

Grazie .................... – AAnkit

risposta

9

Bene, ora vedo il tuo problema. Il problema è che il YAxis (YLabels) determina il numero di cifre e quindi i passaggi tra ciascuna etichetta automaticamente.

Sfortunatamente è attualmente non possibile per personalizzare il modo in cui l'asse si calcola o imposta etichette personalizzate.

Sto pensando di aggiungere una funzione di questo tipo in futuro, in cui l'utente può definire quali valori vengono disegnati come etichette dell'asse.

Solo un suggerimento:

Il mEntries array che contiene tutte le etichette degli assi è pubblico. Quindi, in generale, è possibile modificarlo dopo che è stato creato. Tuttavia, non sono assolutamente sicuro di come si comporterà l'asse se lo si modifica manualmente.

Ma forse vale la pena di provare :-) https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java

+0

Come ho detto nella mia domanda: "Ho tentato di utilizzare un ValueFormatter per arrotondare i valori, ma il problema è che a volte i valori Y non sono in posizioni di valore intero (ad esempio 0.8.1.6,2.4, ecc.) Pertanto, se li modifico solo per essere interi, non saranno nella posizione corretta. " – Fozefy

+0

Certo che lo saranno. Con ValueFormatter, stai semplicemente modificando cosa viene disegnato nelle etichette dei valori. Non stai modificando il valore della voce che viene disegnata. –

+0

Se ho il valore '3.4' e lo cambio in '3', allora quel 3 sarà troppo alto. Inoltre, se ho i valori 2.1 e 2.8 questo mi darebbe due 2. Potrei cambiare il modo in cui giro, ma ciò non risolverà il problema. Si prega di vedere la mia domanda aggiornata per maggiori dettagli. Grazie per l'aiuto! – Fozefy

5

Abbastanza semplice.Tutto ciò che serve è due cose:

  1. Axis valore formattatore

    mChart.getAxisLeft().setValueFormatter(new ValueFormatter() { 
        @Override 
        public String getFormattedValue(float value) { 
         return String.valueOf((int) Math.floor(value)); 
        } 
    }); 
    
  2. Axis conteggio etichetta

    int max = findMaxYValue(yourdata); // figure out the max value in your dataset 
    mChart.getAxisLeft().setLabelCount(max); 
    
+0

È la soluzione più semplice, fornisce anche concatenazione. grazie hai salvato il mio tempo –

6

Ecco come ho risolto questo problema. Sembra che l'asse y sia sempre disegnato 1 sul valore massimo (se non lo forza). Quindi imposta il numero di etichette 2 sul valore massimo (includi zero e uno sul valore massimo), quindi tutto ciò che devi fare è rimuovere il decimale con il formattatore dell'asse. Questo funziona se tutti i valori y sono interi, non sono sicuro di come funzionerebbe con i valori decimali.

barChart.getAxisLeft().setLabelCount(maxYvalue + 2, true); 
    barChart.getAxisLeft().setAxisMinValue(0f); 
    barChart.getAxisLeft().setAxisMaxValue(maxYvalue + 1); 
    YAxisValueFormatter customYaxisFormatter = new YAxisValueFormatter() { 
     @Override 
     public String getFormattedValue(float value, YAxis yAxis) { 
      return String.valueOf((int)value); 
     } 
    }; 
    barChart.getAxisLeft().setValueFormatter(customYaxisFormatter); 
2

so che sto rispondendo molto tardi, ma sto cercando di gettare un po 'di luce su questo problema in modo che i futuri utenti hanno una conoscenza po' di più per quanto riguarda lo stesso.

Ho anche affrontato lo stesso problema. Ho usato MyYAxisValueFormatter per visualizzare solo il valore intero in Y-Axis. Di seguito è riportato il codice per lo stesso.

public class MyYAxisValueFormatter implements YAxisValueFormatter { 

    private DecimalFormat mFormat; 

    public MyYAxisValueFormatter() { 
     mFormat = new DecimalFormat("###,###,##0"); 
    } 

    @Override 
    public String getFormattedValue(float value, YAxis yAxis) { 
     // write your logic here 
     // access the YAxis object to get more information 
     return mFormat.format(value); 
    } 
} 

Utilizzando questa classe che cosa accade è sicuramente visualizza i valori dell'asse Y in formato integer ma anche duplicare qualche valore. Questo a causa della conversione del valore float in intero.

Lasciamo che per esempio 0.4 sia convertito in 0 quindi ci saranno due o potrebbero essere più 0 valori in asse Y.

Penso che questo sia ciò che accade in caso di @Fozefy.

Ho implementato il codice di seguito indicato per risolvere questo problema e il suo lavoro come un fascino. Ho usato la funzione setAxisMaxValue per impostare un valore massimo personalizzato per l'asse Y e setLabelCount per impostare il numero di voci dell'etichetta per l'asse Y.

YAxis yAxis = chart.getAxis(YAxis.AxisDependency.LEFT); 

    // Minimum section is 1.0f, could be 0.25f for float values 
    float labelInterval = 1.0f/2f; 

    int sections; //No of sections in Y-Axis, Means your Highest Y-value. 
    do { 
     labelInterval *= 2; //Interval between labels in Y-Axis 
     sections = ((int) Math.ceil(chart.getYMax()/labelInterval)); 
    } while (sections > 10); 

    // If the ymax lies on one of the top interval, add another one for some spacing 
    if (chart.getYMax() == sections * labelInterval) { 
     sections++; 
    } 

    yAxis.setAxisMaximum(labelInterval * sections); 
    yAxis.setLabelCount(sections + 1, true); 

intervallo etichetta rimane uno se il valore y massimo è inferiore a 10 altrimenti due. È possibile personalizzare questo comportamento in base al proprio requisito e aumentare anche l'intervallo di etichette modificando il ciclo do-while.

anche assicurarsi che si sta utilizzando setLabelCount(int count, boolean force) metodo e passando force valore true.

2

Dopo aver guardato intorno senza alcuna soluzione disponibile, ho deciso di esaminare la javadoc e ho scoperto questo metodo: setGranularity(float).Per forzare l'asse Y per visualizzare sempre numeri interi (o qualsiasi intervallo che si desidera), è sufficiente chiamare questo:

yAxisLeft.setGranularity(1.0f); 
yAxisLeft.setGranularityEnabled(true); // Required to enable granularity 

Tuttavia, se i valori minimo e massimo del grafico è troppo vicino, quindi il grafico non sarà onorare setLabelCount(), se non quando è costretto (che renderà le etichette in decimali di nuovo), quindi è necessario chiamare questo dopo i dati di impostazione:

private void calculateMinMax(BarLineChartBase chart, int labelCount) { 
    float maxValue = chart.getData().getYMax(); 
    float minValue = chart.getData().getYMin(); 

    if ((maxValue - minValue) < labelCount) { 
     float diff = labelCount - (maxValue - minValue); 
     maxValue = maxValue + diff; 
     chart.getAxisLeft().setAxisMaximum(maxValue); 
     chart.getAxisLeft().setAxisMinimum(minValue); 
    } 
} 

E questo è tutto!

+0

Brillante, esattamente quello che stavo cercando, grazie! Una funzionalità come questa potrebbe anche essere chiamata _step size_ o, in questo caso, forse _minimum step size_, è quello che ho cercato senza alcun risultato. –

0

Anch'io ho affrontato lo stesso problema .. Basta usare sotto il codice per sbarazzarsi di esso !!!

chart.getAxisLeft().setValueFormatter(new ValueFormatter() { 
     @Override 
     public String getFormattedValue(float value) { 
      return String.valueOf((int) Math.floor(value)); 
     } 
    }); 

Felice Coding ..

Problemi correlati