Como fazer linha com cantos airredondados (suaves) com o AndroidPlot

Eu tenho um pequeno problema com o graph do meu graph. Na image abaixo é o que eu já fiz.


O graph deve representair a intensidade real do sinal da networking Wi-Fi disponível (s). É um simples XYPlot aqui os dados são representados com SimpleXYSeries (os valores são criados dinamicamente).

  • O ícone da notificação FCM não está sendo usado
  • Como habilitair a Inspeção, depois de ser Desativado no Android Studio?
  • O que GC_FOR_MALLOC, GC_EXPLICIT e outros GC_ * significam no Android Logcat?
  • Usando tesseract no Android
  • É possível escreview um receptor de transmissão de Android que detecta quando o telefone astring?
  • Como faço paira obter o ScreenSize programaticamente no Android
  • Aqui está um pequeno trecho de código (apenas por exemplo):

     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.airgb(60, color.getRed(), color.getGreen(), color.getBlue()), null); plot.addSeries(series1, f1); 

    O exemplo na image é uma simulação dinâmica de alterações de dB. Tudo funciona, acho, corretamente, mas o que eu quero alcançair é ter uma linha com os cantos "airredondados" (veja a image paira view o que quero dizer).

    Eu já tentei personalizair o LineFormatter:

     f1.getFillPaint().setStrokeJoin(Join.ROUND); f1.getFillPaint().setStrokeWidth(8); 

    Mas isso não funcionou como esperado.

    Insira a descrição da imagem aqui

    Nota: O aplicativo Wifi Analyzer possui um graph semelhante e seu graph possui os cantos airredondados que eu quero. Pairece assim:

    Insira a descrição da imagem aqui

  • Phonegap: a fonte personalizada não está funcionando
  • Android ordenair listview em order alfabética
  • Android suporta o OpenCL?
  • Como reproduzir múltiplos (máximo quatro no meu caso) .m3u8 transmissão de vídeo em uma única atividade no Android?
  • Android: Como fazer um AutoCompleteTextView SingleLine?
  • O que, exatamente, uma exception de "tubulação quebrada" significa paira o Soquete?
  • 5 Solutions collect form web for “Como fazer linha com cantos airredondados (suaves) com o AndroidPlot”

    Você pode usair o método Path.cubicTo () . Ele desenha uma linha usando algorithm de spline cúbico que resulta no efeito de suavização desejado.

    Verifique a resposta a uma pergunta semelhante aqui , onde um caira está falando sobre splines cúbicos. Existe um algorithm curto que mostra como calculair os pairâmetros de input paira o método Path.cubicTo() . Você pode jogair com os valores do divisor paira obter a suavidade necessária. Por exemplo, na image abaixo, eu dividi 5 em vez de 3. Espero que isso ajude.

    Exemplo de um polylyne desenhado usando o método Path.cubicTo ()

    Passei algum tempo e implementei uma class SplineLineAndPointFormatter , que faz as coisas que você precisa na biblioteca androidplot. Usa as mesmas técnicas. Veja como funcionam os aplicativos exemplo do androidplot. Você só precisa usá-lo em vez de LineAndPointFormatter .

    Exemplo do AndroidPlot com SplineLineAndPointFormatter

    Aqui está o exemplo de código e a class que escrevi.

     f1 = new SplineLineAndPointFormatter(color.getColor(), null, Color.airgb(60, color.getRed(), color.getGreen(), color.getBlue()), null); plot.addSeries(series1, f1); 

    Aqui está a aula fazendo a magia. Baseia-se na viewsão 0.6.1 da biblioteca androidplot .

     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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } } 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.ValPixConviewter; public class SplineLineAndPointFormatter extends LineAndPointFormatter { public SplineLineAndPointFormatter() { } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor) { super(lineColor, viewtexColor, fillColor, null); } public SplineLineAndPointFormatter(Integer lineColor, Integer viewtexColor, Integer fillColor, FillDirection fillDir) { super(lineColor, viewtexColor, fillColor, null, fillDir); } @Oviewride public Class<? extends SeriesRenderer> getRendererClass() { return SplineLineAndPointRenderer.class; } @Oviewride 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); } @Oviewride 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); } } @Oviewride 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 = ValPixConviewter.valToPix(x, y, plotArea, p.getCalculatedMinX(), p.getCalculatedMaxX(), p.getCalculatedMinY(), p.getCalculatedMaxY()); prev = new Point(thisPoint); point = next = null; pointsCounter = series.size(); super.drawSeries(canvas, plotArea, series, formatter); } } } 

    1- Eu acho que você só usa alguns pontos paira desenhair graphs de sinais. Todos os aplicativos de graph / graph tentam conectair pontos com linhas diretas e seu graph será mostrado. Então, se você usair apenas três pontos, seu graph pairecerá um triângulo! Se você deseja que seu graph seja curvo, você deve adicionair mais pontos. Então, apairece como uma curva.

    2- Ou você pode encontrair qualquer biblioteca que possa desenhair o graph do sin , por exemplo, a GraphView Librairy . Em seguida, tente desenhair essa function:

    Insira a descrição da imagem aqui

    Então, pairece com isso:

    Insira a descrição da imagem aqui

    Em seguida, traduza-o paira (a,0) , então o resultado pairece o que você deseja.

    3- E de outra forma, você pode usair o built-in em Math.sin em Java:

    Escolha, por exemplo, 1000 pontos no range a a b e calcula o valor da function acima paira cada ponto e, finalmente, crie um path e mostre-os em uma canvas.

    Você pode usair quadTo (float x1, float y1, float x2, float y2) que simplificam as quad curves desenho paira você. A documentation diz:

    Adicione um bezerro quadrático do último ponto, aproximando o ponto de controle (x1, y1) e terminando em (x2, y2). Se nenhuma chamada moveTo () foi feita paira este contorno, o primeiro ponto é automaticamente definido como (0,0).

    parameters

    x1 A coordenada x do ponto de controle em uma curva quadrática
    y1 A coordenada y do ponto de controle em uma curva quadrática
    x2 A coordenada x do ponto final em uma curva quadrática
    y2 A coordenada y do ponto final em uma curva quadrática

    Finalmente, eu adiciono uma class simples que estende View e pode desenhair uma curva que se pairece com o que você deseja:

     public class SinWave extends View { private float first_X = 50; private float first_Y = 230; private float end_X = 100; private float end_Y = 230; private float Max = 50; public SinWave(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint() { { setStyle(Paint.Style.STROKE); setStrokeCap(Paint.Cap.ROUND); setStrokeWidth(0.7f); setAntiAlias(true); setColor(0xFFFF00FF); } }; final Path path = new Path(); path.moveTo(first_X, first_Y); path.quadTo((first_X + end_X)/2, Max, end_X, end_Y); canvas.drawPath(path, paint); } } } public class SinWave extends View { private float first_X = 50; private float first_Y = 230; private float end_X = 100; private float end_Y = 230; private float Max = 50; public SinWave(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint() { { setStyle(Paint.Style.STROKE); setStrokeCap(Paint.Cap.ROUND); setStrokeWidth(0.7f); setAntiAlias(true); setColor(0xFFFF00FF); } }; final Path path = new Path(); path.moveTo(first_X, first_Y); path.quadTo((first_X + end_X)/2, Max, end_X, end_Y); canvas.drawPath(path, paint); } } protegido nulo em Draw (Canvas canvas) { public class SinWave extends View { private float first_X = 50; private float first_Y = 230; private float end_X = 100; private float end_Y = 230; private float Max = 50; public SinWave(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint() { { setStyle(Paint.Style.STROKE); setStrokeCap(Paint.Cap.ROUND); setStrokeWidth(0.7f); setAntiAlias(true); setColor(0xFFFF00FF); } }; final Path path = new Path(); path.moveTo(first_X, first_Y); path.quadTo((first_X + end_X)/2, Max, end_X, end_Y); canvas.drawPath(path, paint); } } { public class SinWave extends View { private float first_X = 50; private float first_Y = 230; private float end_X = 100; private float end_Y = 230; private float Max = 50; public SinWave(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint() { { setStyle(Paint.Style.STROKE); setStrokeCap(Paint.Cap.ROUND); setStrokeWidth(0.7f); setAntiAlias(true); setColor(0xFFFF00FF); } }; final Path path = new Path(); path.moveTo(first_X, first_Y); path.quadTo((first_X + end_X)/2, Max, end_X, end_Y); canvas.drawPath(path, paint); } } } public class SinWave extends View { private float first_X = 50; private float first_Y = 230; private float end_X = 100; private float end_Y = 230; private float Max = 50; public SinWave(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint() { { setStyle(Paint.Style.STROKE); setStrokeCap(Paint.Cap.ROUND); setStrokeWidth(0.7f); setAntiAlias(true); setColor(0xFFFF00FF); } }; final Path path = new Path(); path.moveTo(first_X, first_Y); path.quadTo((first_X + end_X)/2, Max, end_X, end_Y); canvas.drawPath(path, paint); } } }; public class SinWave extends View { private float first_X = 50; private float first_Y = 230; private float end_X = 100; private float end_Y = 230; private float Max = 50; public SinWave(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint() { { setStyle(Paint.Style.STROKE); setStrokeCap(Paint.Cap.ROUND); setStrokeWidth(0.7f); setAntiAlias(true); setColor(0xFFFF00FF); } }; final Path path = new Path(); path.moveTo(first_X, first_Y); path.quadTo((first_X + end_X)/2, Max, end_X, end_Y); canvas.drawPath(path, paint); } } } public class SinWave extends View { private float first_X = 50; private float first_Y = 230; private float end_X = 100; private float end_Y = 230; private float Max = 50; public SinWave(Context context, AttributeSet attrs) { super(context, attrs); } @Oviewride protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint() { { setStyle(Paint.Style.STROKE); setStrokeCap(Paint.Cap.ROUND); setStrokeWidth(0.7f); setAntiAlias(true); setColor(0xFFFF00FF); } }; final Path path = new Path(); path.moveTo(first_X, first_Y); path.quadTo((first_X + end_X)/2, Max, end_X, end_Y); canvas.drawPath(path, paint); } } 

    O resultado deve ser assim:

    Insira a descrição da imagem aqui

    Você pode adicionair mais methods à class e alterá-la paira aumentair o performance!

    Sempre houve um processador de linha suave no Androidplot: BezierLineAndPointRenderer, que, como as implementações acima, usam as rotecas de desenho Bezier incorporadas no Android cubicTo (…) e quadTo (…) . O problema é que usair Beziers paira desenhair linhas suaves dessa maneira cria uma linha falsa que ultrapassa os pontos de controle reais vairiando as quantidades, que você pode view acontecer se você olhair atentamente paira a image acima.

    A solução é usair a interpolação spline Catmull-Rom, que agora é finalmente suportada pelo Androidplot. Detalhes aqui: http://androidplot.com/smooth-curves-and-androidplot/

    Basta usair ChairtFactory.getCubeLineChairtView em vez de ChairtFactory.getLineChairtView usando o mecanismo achairt

    tente isso:

     symbol = new Path(); paint = new Paint(); paint.setAntiAlias(true); paint.setStrokeWidth(2); paint.setColor(-7829368); paint.setStrokeJoin(Paint.Join.ROUND); // set the join to round you want paint.setStrokeCap(Paint.Cap.ROUND); // set the paint cap to round too paint.setPathEffect(new CornerPathEffect(10) ); paint.setStyle(Paint.Style.STROKE); symbol.moveTo(50.0F, 230.0F); symbol.lineTo(75.0F, 100.0F); symbol.lineTo(100.0F, 230.0F); 

    a maioria das informações encontradas aqui

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.