2017-04-11 7 views
2

enter image description hereAndroid - Füllen Sie die Farbe zwischen zwei Linien mit MPAndroidChart

ich setFillFormatter verwende, aber es hilft nicht, mir und SetFillColor() die zweite Linie kreuzt (schwarz), da es keine Möglichkeit gibt, die zu stoppen erste Zeile (Gelb) bei Y-Werten der zweiten Zeile. Ich möchte so etwas implementieren:

dataSet.setFillFormatter(new IFillFormatter() { 

      @Override 
      public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { 
       return //return Y value of the second line for current X of line being filled; 
      } 
     }); 

Gibt es einen Weg, um den Y-Wert der zweiten Zeile für jedes X der ersten Zeile zu finden? Ich sehe beide dataSet und dataProvider liefert feste Werte für jeden Aufruf von getFillLinePosition.

+1

Ich glaube nicht, dass Sie mit den mitgelieferten Methoden in der Bibliothek tun. Sie müssen wahrscheinlich einen benutzerdefinierten Renderer schreiben, um dies zu tun. Sieh dir 'LineChartRenderer' an –

Antwort

3

Danke David Rawson für mich in Richtung LineChartRenderer. Ich bin in der Lage, den Bereich zwischen zwei Linien zu färben.

Wir müssen zwei wichtige Änderungen vornehmen.

  1. Implementieren Sie eine benutzerdefinierte FillFormator, um den Datensatz einer anderen Zeile zurückzugeben.

    public class MyFillFormatter implements IFillFormatter { 
    private ILineDataSet boundaryDataSet; 
    
    public MyFillFormatter() { 
        this(null); 
    } 
    //Pass the dataset of other line in the Constructor 
    public MyFillFormatter(ILineDataSet boundaryDataSet) { 
        this.boundaryDataSet = boundaryDataSet; 
    } 
    
    @Override 
    public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { 
        return 0; 
    } 
    
    //Define a new method which is used in the LineChartRenderer 
    public List<Entry> getFillLineBoundary() { 
        if(boundaryDataSet != null) { 
         return ((LineDataSet) boundaryDataSet).getValues(); 
        } 
        return null; 
    }} 
    
  2. Implementieren eines benutzerdefinierten LineChartRenderer auf die beigefügten Pfad zu ziehen und zu füllen.

    public class MyLineLegendRenderer extends LineChartRenderer { 
    
    public MyLineLegendRenderer(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { 
        super(chart, animator, viewPortHandler); 
    } 
    
    //This method is same as it's parent implemntation 
    @Override 
    protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, XBounds bounds) { 
        final Path filled = mGenerateFilledPathBuffer; 
    
        final int startingIndex = bounds.min; 
        final int endingIndex = bounds.range + bounds.min; 
        final int indexInterval = 128; 
    
        int currentStartIndex = 0; 
        int currentEndIndex = indexInterval; 
        int iterations = 0; 
    
        // Doing this iteratively in order to avoid OutOfMemory errors that can happen on large bounds sets. 
        do { 
         currentStartIndex = startingIndex + (iterations * indexInterval); 
         currentEndIndex = currentStartIndex + indexInterval; 
         currentEndIndex = currentEndIndex > endingIndex ? endingIndex : currentEndIndex; 
    
         if (currentStartIndex <= currentEndIndex) { 
          generateFilledPath(dataSet, currentStartIndex, currentEndIndex, filled); 
    
          trans.pathValueToPixel(filled); 
    
          final Drawable drawable = dataSet.getFillDrawable(); 
          if (drawable != null) { 
    
           drawFilledPath(c, filled, drawable); 
          } else { 
    
           drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); 
          } 
         } 
    
         iterations++; 
    
        } while (currentStartIndex <= currentEndIndex); 
    } 
    
    //This is where we define the area to be filled. 
    private void generateFilledPath(final ILineDataSet dataSet, final int startIndex, final int endIndex, final Path outputPath) { 
    
        //Call the custom method to retrieve the dataset for other line 
        final List<Entry> boundaryEntry = ((MyFillFormatter)dataSet.getFillFormatter()).getFillLineBoundary(); 
    
        final float phaseY = mAnimator.getPhaseY();  
        final Path filled = outputPath; 
        filled.reset(); 
    
        final Entry entry = dataSet.getEntryForIndex(startIndex); 
    
        filled.moveTo(entry.getX(), boundaryEntry.get(0).getY()); 
        filled.lineTo(entry.getX(), entry.getY() * phaseY); 
    
        // create a new path 
        Entry currentEntry = null; 
        Entry previousEntry = null; 
        for (int x = startIndex + 1; x <= endIndex; x++) { 
    
         currentEntry = dataSet.getEntryForIndex(x); 
         filled.lineTo(currentEntry.getX(), currentEntry.getY() * phaseY); 
    
        } 
    
        // close up 
        if (currentEntry != null && previousEntry!= null) { 
         filled.lineTo(currentEntry.getX(), previousEntry.getY()); 
        } 
    
        //Draw the path towards the other line 
        for (int x = endIndex ; x > startIndex; x--) { 
         previousEntry = boundaryEntry.get(x); 
         filled.lineTo(previousEntry.getX(), previousEntry.getY() * phaseY); 
        } 
    
        filled.close(); 
    }} 
    
  3. Am Ende der Aktivität

    Stellen Sie die MyFillFormatter einem der LineDataSet andere LineDataSet als Argument übergeben.

    lineDataSet2.setFillFormatter(new MyFillFormatter(LineDataSet1)); 
    
    mChart.setRenderer(new MyLineLegendRenderer(mChart, mChart.getAnimator(), mChart.getViewPortHandler())); 
    

enter image description here

Verwandte Themen