MPAndroidChart 折线图 自定义高亮 drawable

14

我正在使用MPAndroid Chart库在我的Android应用程序中绘制折线图。图表的状态如下:

MPAndroidChart -  Line Chart

我想要将它改为这个样子:

Line Chart

因此,我想要更改MPAnroid折线图中的数据点,这被称为库中的“Circle Hole”。 我可以通过可绘制对象来替换这个圆形洞吗?

更改圆形洞的代码如下:

LineDataSet set1 = new LineDataSet(yVals, "DataSet 1");
set1.setDrawCircleHole( true );
set1.setCircleColor( Color.BLACK );

这里是图表库的参考文档:MPAndroidChart


“将此孔切换为可绘制项”是什么意思?您是否想要自己的可绘制项而不是CircleHole? - Paamand
你找到更改高亮可绘制对象的解决方案了吗? - Massimo
@Massimo,请查看我的更新答案,其中包括示例代码。 - David Rawson
1个回答

15

自版本3.0以来,您可以提供自己的自定义图像,该图像将在选择图表上的给定点时显示。以下说明与wiki相同。

总之,现在您可以使用名为MarkerImage的类:

MarkerImage myMarkerImage = new MarkerImage(this, R.drawable.my_drawable);

那么:

myChart.setMarker(myMarkerImage);

要调整图像的位置,您可以调用:

setOffset(float x, float y);
如果您不想使用MarkerView,可能需要制作自己的子类来继承LineChartRenderer,并添加逻辑以绘制自定义的高亮可绘制对象。
这是一个非常基本的概念证明示例:
import android.graphics.Bitmap;
import android.graphics.Canvas;

import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.renderer.LineChartRenderer;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.ViewPortHandler;

import java.util.List;

/**
 * Created by David on 3/01/2017.
 */

public class ImageLineChartRenderer extends LineChartRenderer {

    private final LineChart lineChart;
    private final Bitmap image;

    public ImageLineChartRenderer(LineChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler, Bitmap image) {
        super(chart, animator, viewPortHandler);
        this.lineChart = chart;
        this.image = image;
    }

    @Override
    public void drawExtras(Canvas c) {
        super.drawExtras(c);

        Highlight[] highlighted = lineChart.getHighlighted();
        if (highlighted == null) return;

        float phaseY = mAnimator.getPhaseY();

        float[] imageBuffer = new float[2];
        imageBuffer[0] = 0;
        imageBuffer[1] = 0;
        LineData lineData = mChart.getLineData();
        List<ILineDataSet> dataSets = mChart.getLineData().getDataSets();

        Bitmap[] scaledBitmaps = new Bitmap[dataSets.size()];
        float[] scaledBitmapOffsets = new float[dataSets.size()];
        for (int i = 0; i < dataSets.size(); i++) {
            float imageSize = dataSets.get(i).getCircleRadius() * 10;
            scaledBitmapOffsets[i] = imageSize / 2f;
            scaledBitmaps[i] = scaleImage((int) imageSize);
        }

        for (Highlight high : highlighted) {
            int dataSetIndex = high.getDataSetIndex();
            ILineDataSet set = lineData.getDataSetByIndex(dataSetIndex);
            Transformer trans = lineChart.getTransformer(set.getAxisDependency());

            if (set == null || !set.isHighlightEnabled())
                continue;

            Entry e = set.getEntryForXValue(high.getX(), high.getY());

            if (!isInBoundsX(e, set))
                continue;

            imageBuffer[0] = e.getX();
            imageBuffer[1] = e.getY() * phaseY;
            trans.pointValuesToPixel(imageBuffer);

            c.drawBitmap(scaledBitmaps[dataSetIndex],
                    imageBuffer[0] - scaledBitmapOffsets[dataSetIndex],
                    imageBuffer[1] - scaledBitmapOffsets[dataSetIndex],
                    mRenderPaint);
        }
    }

    private Bitmap scaleImage(int radius) {
        return Bitmap.createScaledBitmap(image, radius, radius, false);
    }
}

这样来食用:

Bitmap starBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.star);
mChart.setRenderer(new ImageLineChartRenderer(mChart, mChart.getAnimator(), mChart.getViewPortHandler(), starBitmap));

说明:在 LineChartRenderer 中,drawExtras 会绘制圆圈。我们仍然需要它们,因此在我们的 drawExtras 中,我们首先调用 super 方法。然后为每个 DataSet(DataSets 可能具有不同的圆点半径)生成一个缩放的位图。我们将位图缩放到任意大小(10 倍的圆点半径)。然后,我们通过我们的渲染器的 LineChart 字段公开的 Highlights 进行迭代,并绘制相应的位图。

这是一张截图 - 您可以看到在突出显示的索引上,星形代替了圆圈:

a line chart with a star instead of a circle at the highlighted point


1
谢谢你,@David Rawson,你救了我!我的代码是myChart.setMarker(myMarkerImage),但它对我不起作用,它会覆盖我的MarkerView。我尝试了你的基本概念,它可以工作,虽然对我来说有些困难。非常感谢你。 - Morton
1
这个问题是关于如何编写自定义渲染器的更多信息:https://dev59.com/CKDia4cB1Zd3GeqPL_Sp - David Rawson
1
已经很久了,你仍然分享信息,谢谢。 - Morton
@徐博俊,非常欢迎你!我很高兴能帮到你——只是在链接有关自定义渲染器的问题。 - David Rawson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接