我有一个小问题,打搅我的图表.在下面的图片上我已经做了.
图表应该表示可用Wi-Fi网络的实际信号强度.这是一个简单的XYPlot,这里的数据用SimpleXYSeries表示(值是动态创建的).
以下是一小段代码(仅举例):
plot = (XYPlot) findViewById(R.id.simplexyPlot); series1 = new SimpleXYSeries(Arrays.asList(series1Numbers),SimpleXYSeries.ArrayFormat.Y_VALS_ONLY,"Link 1"); f1 = new LineAndPointFormatter(color.getColor(),null,Color.argb(60,color.getRed(),color.getGreen(),color.getBlue()),null); plot.addSeries(series1,f1);
图中的例子是dB变化的动态模拟.一切正常,我猜,正确的是,但我想要实现的是具有“圆角”的角落(见图片看看我的意思).
我已经尝试自定义LineFormatter:
f1.getFillPaint().setStrokeJoin(Join.ROUND); f1.getFillPaint().setStrokeWidth(8);
但这没有按预期的方式工作.
注意:Wifi Analyzer应用程序具有相似的图形,其图形具有我想要的圆角.看起来像这样:
解决方法
您可以使用
Path.cubicTo()方法.它使用三次样条算法绘制一条线,其导致所需的平滑效果.
结束一个similar question here的答案,一个人在谈论三次样条.有一个简短的算法显示如何计算Path.cubicTo()方法的输入参数.您可以使用分频值来实现所需的平滑度.例如,在下面的图片中,我除以5而不是3.希望这有帮助.
我花了一些时间,并实现了一个SplineLineAndPointFormatter类,它在androidplot库中完成所需的工作.它使用相同的技术.这是androidplot示例应用程序的样子.你只需要使用它而不是LineAndPointFormatter.
这里是代码示例和我写的类.
f1 = new SplineLineAndPointFormatter(color.getColor(),f1);
这是做魔术的班.它基于androidplot库的0.6.1版本.
package com.androidplot.xy; import android.graphics.Canvas; import android.graphics.Path; import android.graphics.PointF; import android.graphics.RectF; import com.androidplot.ui.SeriesRenderer; import com.androidplot.util.ValPixConverter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor,Integer vertexColor,Integer fillColor) { super(lineColor,vertexColor,fillColor,null); } public SplineLineAndPointFormatter(Integer lineColor,Integer fillColor,FillDirection fillDir) { super(lineColor,fillDir); } @Override public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Override public SeriesRenderer getRendererInstance(XYPlot plot) { return new SplineLineAndPointRenderer(plot); } public static class SplineLineAndPointRenderer extends LineAndPointRenderer<BezierLineAndPointFormatter> { static class Point { public float x,y,dx,dy; public Point(PointF pf) { x = pf.x; y = pf.y; } } private Point prev,point,next; private int pointsCounter; public SplineLineAndPointRenderer(XYPlot plot) { super(plot); } @Override protected void appendToPath(Path path,final PointF thisPoint,PointF lastPoint) { pointsCounter--; if (point == null) { point = new Point(thisPoint); point.dx = ((point.x - prev.x) / 5); point.dy = ((point.y - prev.y) / 5); return; } else if (next == null) { next = new Point(thisPoint); } else { prev = point; point = next; next = new Point(thisPoint); } point.dx = ((next.x - prev.x) / 5); point.dy = ((next.y - prev.y) / 5); path.cubicTo(prev.x + prev.dx,prev.y + prev.dy,point.x - point.dx,point.y - point.dy,point.x,point.y); if (pointsCounter == 1) { // last point next.dx = ((next.x - point.x) / 5); next.dy = ((next.y - point.y) / 5); path.cubicTo(point.x + point.dx,point.y + point.dy,next.x - next.dx,next.y - next.dy,next.x,next.y); } } @Override protected void drawSeries(Canvas canvas,RectF plotArea,XYSeries series,LineAndPointFormatter formatter) { Number y = series.getY(0); Number x = series.getX(0); if (x == null || y == null) throw new IllegalArgumentException("no null values in xyseries permitted"); XYPlot p = getPlot(); PointF thisPoint = ValPixConverter.valToPix(x,plotArea,p.getCalculatedMinX(),p.getCalculatedMaxX(),p.getCalculatedMinY(),p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas,series,formatter); } } }