2016-01-31 1 views
3

Я хочу сделать раскрашенный HorizontalBarChart с закругленными краями, используя MPAndroidChart. Я пытаюсь изменить HorizontalBarChartRenderer для своей диаграммы. Вот мой код:MPAndroidchart закругленные края для раскрашенных HorizontalBarChart

HorizontalBarChart инициализации:

List<Float> values = new ArrayList<>(); 
List<Integer> colors = new ArrayList<>(); 
// initializing 

float[] valuesArray = new float[values.size()]; 
for (int i = 0; i < values.size(); i++) { 
    valuesArray[i] = values.get(i); 
} 
List<BarEntry> yValues = valuesArray.length <= 0 
    ? Collections.<BarEntry>emptyList() 
    : Collections.singletonList(new BarEntry(valuesArray, 0)); 
BarDataSet barDataSet = new BarDataSet(yValues, ""); 
barDataSet.setColors(colors); 
barDataSet.setValueFormatter(new ValueFormatter() { 
    @Override 
    public String getFormattedValue(float value, Entry entry, 
     int dataSetIndex, ViewPortHandler viewPortHandler) { 
      return ""; 
     } 
}); 
chartView.setData(new BarData(new String[]{"sleep"}, barDataSet)); 

и продлил HorizontalBarChartRenderer:

@Override 
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { 
    // ... 
    c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1] + 10, buffer.buffer[j + 2], buffer.buffer[j + 3] - 10), 20, 20, mRenderPaint); 
} 

Результат:
current result

Как я могу сделать закругленные края только для внешних сторон ?
Что-то вроде этого:
desired result

ответ

0

Я нашел решение. Моя идея состоит в том, чтобы нарисовать данные как обычно и после очистки некоторых областей, чтобы края были округлены. Мой код:

public class CircleHorizontalBarChartRenderer extends HorizontalBarChartRenderer { 

    public CircleHorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { 
     super(chart, animator, viewPortHandler); 
    } 

    @Override 
    protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { 
     Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); 

     mShadowPaint.setColor(dataSet.getBarShadowColor()); 

     float phaseX = mAnimator.getPhaseX(); 
     float phaseY = mAnimator.getPhaseY(); 

     // initialize the buffer 
     BarBuffer buffer = mBarBuffers[index]; 
     buffer.setPhases(phaseX, phaseY); 
     buffer.setBarSpace(dataSet.getBarSpace()); 
     buffer.setDataSet(index); 
     buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); 

     buffer.feed(dataSet); 

     trans.pointValuesToPixel(buffer.buffer); 

     int length = buffer.buffer.length; 
     float left = 0; 
     float right = 0; 
     float top = buffer.buffer[length - 3]; 
     float bot = buffer.buffer[length - 1]; 
     boolean leftSaved = false; 

     for (int j = 0; j < buffer.size(); j += 4) { 

      if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 3])) 
       break; 

      if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[j + 1])) 
       continue; 

      // Set the color for the currently drawn value. 
      // If the index is 
      // out of bounds, reuse colors. 
      int color = dataSet.getColor(j/4); 
      mRenderPaint.setColor(color); 
      if (color != 0 && !leftSaved) { 
       leftSaved = true; 
       left = buffer.buffer[j]; 
      } 
      if (j > 4) { // it works but its ugly 
       right = buffer.buffer[j - 2]; 
      } 

      c.drawRect(buffer.buffer[j], buffer.buffer[j + 1] + 10, buffer.buffer[j + 2], 
        buffer.buffer[j + 3] - 10, mRenderPaint); 
     } 

     Paint erasePaint = new Paint(); 
     erasePaint.setAntiAlias(true); 
     erasePaint.setStyle(Paint.Style.STROKE); 
     int paintWidth = 20; 
     erasePaint.setStrokeWidth(paintWidth); 
     erasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 
     c.drawRoundRect(new RectF(left - paintWidth/2, top, right + paintWidth/2, bot), 30, 30, erasePaint); 
    } 

} 

PorterDuff.Mode.CLEAR будет работать только если вы установите тип слоя в качестве программного обеспечения. Поэтому вам необходимо позвонить по телефону

setLayerType(View.LAYER_TYPE_SOFTWARE, null); 

для chartView или его родительского вида. Если вам не нужен прозрачный фон и цвет фона в известном, вы можете установить этот цвет для erasePaint и обойтись без типа слоя sowtware, что может ухудшить производительность. И erasePaint.setXfermode также не понадобится для этого случая.

Окончательный результат: enter image description here

0

Я полагаю, что вы рисуете все бары, кроме последнего в «нормальном» режиме, и начать рисовать сверху (округляя) бар первый и пусть растянуть по всей длине всех бары.

Таким образом, другие бруски, которые не закруглены, будут закрывать нежелательные закругления в нижней части первого нарисованного (закругленного) стержня.

 Смежные вопросы

  • Нет связанных вопросов^_^