我想在我的 MPAndroidChart 中按以下顺序绘制(从下到上):
- 数据连接线
- 限制线
- 数据点
这可能吗?我知道 com.github.mikephil.charting.components.AxisBase#setDrawLimitLinesBehindData
方法。除一种情况外,它按预期工作。当所有数据点的Y值都相同时,效果为:
或者这个:
我希望它看起来像:
前2张图片来自MPAndroidChart安卓库。第三个来自库的 iOS 端口:Charts
我查看了Android中的订单或绘制图表和 iOS版本,它们看起来一样。
问题:
- 是否可以控制绘制顺序?
- 系统版本之间有什么区别?
- 是否有任何其他开源库可以做到这一点?
附加信息:所有图像、线条、圆圈均由库绘制,未使用自定义图像。
最佳答案
类似于a previous answer here没有公开的 API 可以直接设置各种绘图功能的 z-index。
相反,组件在 Canvas 上按顺序绘制,后面的组件绘制在前面的组件之上。这意味着你改变渲染顺序,你可以改变 z-index。
你说你想要以下绘图顺序:
- Data connecting line
- Limit line
- Data points
让我们在源代码中找到处理每一个的方法:
数据连接线画在里面
LineChartRenderer
在一个名为的方法中:protected drawLinear(Canvas c, ILineDataSet dataSet)
限制线画在里面
XAxisRenderer
称为:public void renderLimitLines(Canvas c)
数据点(圆圈)绘制在
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/