【问题标题】:MPAndroidChart - is it possible to control z-index of the chart elements?MPAndroidChart - 是否可以控制图表元素的 z-index?
【发布时间】:2017-01-16 04:18:41
【问题描述】:

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

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

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

或者这个:

我希望它看起来像:

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

我查看了AndroidiOS 版本中的订单或绘制图表,它们看起来相同。

问题:

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

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

【问题讨论】:

    标签: android charts mpandroidchart


    【解决方案1】:

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

    相反,组件在画布上按顺序绘制,后面的组件被绘制在前面的组件上。这意味着您更改渲染顺序,您可以更改 z-index。

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

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

    让我们在源代码中找到处理这些方法的方法:

    1. 数据连接线在LineChartRenderer内部通过一个名为的方法绘制:

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

      public void renderLimitLines(Canvas c)
      
    3. 数据点(圆圈)在LineChartRenderer 内以如下所示的方法绘制:

      public void drawExtras(Canvas c)
      

    这三个方法的调用顺序是在Android的View重写的方法中的BarLineChartBase内部确定的:

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-24
    • 2011-03-23
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 2019-11-17
    • 1970-01-01
    相关资源
    最近更新 更多