android - MPAndroidChart - 是否可以控制图表元素的 z-index?

标签 android charts mpandroidchart

我想在我的 MPAndroidChart 中按以下顺序绘制(从下到上):

  1. 数据连接线
  2. 限制线
  3. 数据点

这可能吗?我知道 com.github.mikephil.charting.components.AxisBase#setDrawLimitLinesBehindData 方法。除一种情况外,它按预期工作。当所有数据点的Y值都相同时,效果为:

enter image description here

或者这个:

enter image description here

我希望它看起来像:

enter image description here

前2张图片来自MPAndroidChart安卓库。第三个来自库的 iOS 端口:Charts

我查看了Android中的订单或绘制图表和 iOS版本,它们看起来一样。

问题:

  1. 是否可以控制绘制顺序?
  2. 系统版本之间有什么区别?
  3. 是否有任何其他开源库可以做到这一点?

附加信息:所有图像、线条、圆圈均由库绘制,未使用自定义图像。

最佳答案

类似于a previous answer here没有公开的 API 可以直接设置各种绘图功能的 z-index。

相反,组件在 Canvas 上按顺序绘制,后面的组件绘制在前面的组件之上。这意味着你改变渲染顺序,你可以改变 z-index。

你说你想要以下绘图顺序:

  1. Data connecting line
  2. Limit line
  3. Data points

让我们在源代码中找到处理每一个的方法:

  1. 数据连接线画在里面LineChartRenderer在一个名为的方法中:

    protected drawLinear(Canvas c, ILineDataSet dataSet)
    
  2. 限制线画在里面XAxisRenderer称为:

    public void renderLimitLines(Canvas c)
    
  3. 数据点(圆圈)绘制在LineChartRenderer内在一个看起来像这样的方法中:

    public void drawExtras(Canvas c)
    

这三个方法的调用顺序是在BarLineChartBase里面决定的在从 Android 的 View 覆盖的方法中:

    protected onDraw(Canvas canvas);

因此,要获得您想要的顺序,您只需重新安排 onDraw(Canvas canvas) 中上述​​ 3 个方法的调用顺序:

下面是满足要求的自定义折线图的完整代码。按照设计,您仍然需要调用:

com.github.mikephil.charting.components.AxisBase#setDrawLimitLinesBehindData

但是如果您愿意,您可以轻松删除 3 个 if 语句并硬编码顺序。

CustomZIndexBarLineBase.java

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;

import com.github.mikephil.charting.charts.BarLineChartBase;
import com.github.mikephil.charting.data.LineData;

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

public class CustomZIndexLineChartBase extends BarLineChartBase<LineData> {

    public CustomZIndexLineChartBase(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CustomZIndexLineChartBase(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomZIndexLineChartBase(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mData == null)
            return;

        // execute all drawing commands
        drawGridBackground(canvas);

        if (mAxisLeft.isEnabled())
            mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum, mAxisLeft.isInverted());
        if (mAxisRight.isEnabled())
            mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum, mAxisRight.isInverted());
        if (mXAxis.isEnabled())
            mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false);

        mXAxisRenderer.renderAxisLine(canvas);
        mAxisRendererLeft.renderAxisLine(canvas);
        mAxisRendererRight.renderAxisLine(canvas);

        if (mAutoScaleMinMaxEnabled) {
            autoScale();
        }

        mXAxisRenderer.renderGridLines(canvas);
        mAxisRendererLeft.renderGridLines(canvas);
        mAxisRendererRight.renderGridLines(canvas);

        if (mXAxis.isDrawLimitLinesBehindDataEnabled())
            mXAxisRenderer.renderLimitLines(canvas);

        if (mAxisLeft.isDrawLimitLinesBehindDataEnabled())
            mAxisRendererLeft.renderLimitLines(canvas);

        if (mAxisRight.isDrawLimitLinesBehindDataEnabled())
            mAxisRendererRight.renderLimitLines(canvas);

        int clipRestoreCount = canvas.save();
        canvas.clipRect(mViewPortHandler.getContentRect());

        mRenderer.drawData(canvas); //NOTE: draws line between points


        if (valuesToHighlight())
            mRenderer.drawHighlighted(canvas, mIndicesToHighlight);

        canvas.restoreToCount(clipRestoreCount);

        //NOTE: draws limit line
        if (!mXAxis.isDrawLimitLinesBehindDataEnabled())
            mXAxisRenderer.renderLimitLines(canvas);

        if (!mAxisLeft.isDrawLimitLinesBehindDataEnabled())
            mAxisRendererLeft.renderLimitLines(canvas);

        if (!mAxisRight.isDrawLimitLinesBehindDataEnabled())
            mAxisRendererRight.renderLimitLines(canvas);

        mRenderer.drawExtras(canvas); //NOTE: draws circles

        mXAxisRenderer.renderAxisLabels(canvas);
        mAxisRendererLeft.renderAxisLabels(canvas);
        mAxisRendererRight.renderAxisLabels(canvas);

        if (isClipValuesToContentEnabled()) {
            clipRestoreCount = canvas.save();
            canvas.clipRect(mViewPortHandler.getContentRect());

            mRenderer.drawValues(canvas);

            canvas.restoreToCount(clipRestoreCount);
        } else {
            mRenderer.drawValues(canvas);
        }

        mLegendRenderer.renderLegend(canvas);

        drawDescription(canvas);

        drawMarkers(canvas);
    }
}

CustomZIndexLineChart.java

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;

import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider;
import com.github.mikephil.charting.renderer.LineChartRenderer;

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

public class CustomZIndexLineChart extends CustomZIndexLineChartBase implements LineDataProvider {

    public CustomZIndexLineChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CustomZIndexLineChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomZIndexLineChart(Context context) {
        super(context);
    }

    @Override
    protected void init() {
        super.init();

        mRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    @Override
    public LineData getLineData() {
        return mData;
    }

    @Override
    protected void onDetachedFromWindow() {
        // releases the bitmap in the renderer to avoid oom error
        if (mRenderer != null && mRenderer instanceof LineChartRenderer) {
            ((LineChartRenderer) mRenderer).releaseBitmap();
        }
        super.onDetachedFromWindow();
    }
}

关于android - MPAndroidChart - 是否可以控制图表元素的 z-index?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39387434/

相关文章:

java - 如何在 Android 上高效存储位集

android - 换行短信安卓

javascript - 需要通过鼠标拖动选择google散点图中点的范围

android - 如何从 json url 加载图表值并在 mpandroidchart 中显示

java - findViewById 用于在包含的合并根元素内查看

Android 选项卡不填写父项

c# - 如何在图表上设置系列颜色?

reactjs - Recharts ScatterChart 未在 XAxis 中渲染点和重复值

android - MPAndroidChart x 轴日期/时间标签格式

android - MPAndroidChart BarChart 条被切断