【问题标题】:MPAndroidchart rounded edges for colorized HorizontalBarChartMPAndroidchart 圆形边缘用于彩色 Horizo​​ntalBarChart
【发布时间】:2016-05-08 19:08:21
【问题描述】:

我想使用MPAndroidChart 制作一个带有圆边的彩色Horizo​​ntalBarChart。我正在尝试为我的图表更改 Horizo​​ntalBarChartRenderer。这是我的代码:

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

结果是:

如何只为外侧制作圆边?
像这样:

【问题讨论】:

    标签: java android bar-chart mpandroidchart


    【解决方案1】:

    我建议您在“正常”模式下绘制除最后一个之外的所有条形图,并首先绘制顶部(圆形)条形图,让它在所有条形图的整个长度上延伸。

    这样,其他未圆角的条形将覆盖第一个绘制(圆形)条形底部不需要的圆角。

    【讨论】:

      【解决方案2】:

      我找到了解决方案。我的想法是像往常一样绘制数据,并在清除一些区域以使边缘变圆之后。 我的代码:

      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 设置此颜色,并且不要使用会降低性能的软件层类型。在这种情况下也不需要erasePaint.setXfermode。

      最终结果:

      【讨论】:

        【解决方案3】:

        我编辑了 Nick Kober 的解决方案。这是代码;

        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.setBarWidth(dataSet.getBarBorderWidth());
                buffer.setDataSet(index);
                buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
        
                buffer.feed(dataSet);
        
                trans.pointValuesToPixel(buffer.buffer);
        
                int timeToChange = buffer.size() / 4;
        
                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 (j/4 == 0) {
                        c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1] + 10, buffer.buffer[j+2], buffer.buffer[j + 3] - 10), 20, 20, mRenderPaint);
                        c.drawRect(new RectF(buffer.buffer[j] + 10 , buffer.buffer[j + 1] + 10, buffer.buffer[j+2], buffer.buffer[j + 3] - 10), mRenderPaint);
                    }
                    else if (j/4 < timeToChange - 1) {
                        c.drawRect(new RectF(buffer.buffer[j] , buffer.buffer[j + 1] + 10, buffer.buffer[j+2], buffer.buffer[j + 3] - 10), mRenderPaint);
                    }
                    else if (j/4 == timeToChange - 1) {
                        c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1] + 10, buffer.buffer[j+2], buffer.buffer[j + 3] - 10), 20, 20, mRenderPaint);
                        c.drawRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1] + 10, buffer.buffer[j+2] - 10, buffer.buffer[j + 3] - 10), mRenderPaint);
                    }
                }
            }
        

        同样,您应该像 Nick 那样编写自己的自定义 Renderer 类。我添加了最后一部分(if-else if 块)。

        我是这样想的,为第一条画圆角矩形。然后在上面通过将左侧移动到右侧来绘制一个矩形。通过移位,左侧保持圆形。对于内部的,将它们全部绘制为矩形。最后一个画圆角矩形。然后在其上方通过将右侧向左移动来绘制一个矩形。通过移位,右侧保持圆形。

        我使用变量“timeToChange”来了解我当前正在绘制哪个条形图。

        And the output is like this

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-05-30
          • 2019-03-25
          • 1970-01-01
          • 1970-01-01
          • 2018-11-14
          • 1970-01-01
          • 2022-09-28
          • 1970-01-01
          相关资源
          最近更新 更多