halfhp / androidplot Goto Github PK
View Code? Open in Web Editor NEWCharts and plots for Android
Home Page: http://androidplot.com
License: Apache License 2.0
Charts and plots for Android
Home Page: http://androidplot.com
License: Apache License 2.0
I noticed a differenced with how the graph widget is being anchored (not sure if that's the right word to use) within it's layout. In version 0.9.8 of the library, the graph seems to take up all amount of reasonable space within the layout. However, in version 1.4.3 (which I believe is the latest), there is a giant margin below the graph.
Version 0.9.8:
Version 1.4.3:
I even tested this with a completely stripped down project which just has the XML layout setup:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:ap="http://schemas.android.com/apk/res-auto"
android:background="#0099cc">
<!-- The primary full-screen view. This can be replaced with whatever view
is needed to present your content, e.g. VideoView, SurfaceView,
TextureView, etc. -->
<com.androidplot.xy.XYPlot
style="@style/APDefacto.Light"
android:id="@+id/fullscreen_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
ap:title="A Simple XY Plot"/>
<!-- This FrameLayout insets its children based on system windows using
android:fitsSystemWindows. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:id="@+id/fullscreen_content_controls"
style="?metaButtonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="@color/black_overlay"
android:orientation="horizontal"
tools:ignore="UselessParent">
<Button
android:id="@+id/dummy_button"
style="?metaButtonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/dummy_button"/>
</LinearLayout>
</FrameLayout>
</FrameLayout>
What can I do to get rid of this margin below the graph or to otherwise make the graph layout behave in the same manner as it did in the earlier version?
This is a full-screen application, if that helps.
Despite doing
mPlot.getGraph().setRangeGridLinePaint(null);
mPlot.getGraph().setDomainGridLinePaint(null);
my bar chart's grid horizontal lines are still visibles.
I'm using style APDefacto.Dark
I've also asked the question here:
https://stackoverflow.com/questions/48620565/how-to-hide-horizontal-range-lines-on-androidplots-xyplot
protected float seriesToScreenY(Number y) { return (float) plot.getBounds().getyRegion(). transform(y.doubleValue(), gridRect.left, gridRect.right, true); }
In the above code, this is a Y coordinate conversion, so the min/max values should be gridRect.bottom/top not left/right
This might be a dumb question but I am looking at the demo code for the ecg example, and was wondering where the line "R.id.plot" came from, and what it means to the broader code. Thank you in advance.
In real-time plotting, onClick on the graph how to display particular values with marker.
onPlotClicked() for real time data.
This is a test issue.
Thank you for making a very useful library. It really helps. There is a favor to ask. I'd like you to create a release tag of version 1.4.1 Thank you.
This feature is broken and crashes the app (including the demo app). Try tapping out of the Zoom example.
As far as I can see the bundle.putSerializable("seriesRegistry", plot.getRegistry());
call tries to serialize stuff that is not serializeable like Paint objects.
The following code results in an plot that only shows vertices, but no lines or shading:
plot.addSeries(new SimpleXYSeries(
Arrays.asList(new Float[]{0f, 1f, 2f, 3f, 4f}),
Arrays.asList(new Float[]{5f, 6f, Float.NaN, 4f, 2f}),
"Data"
), new LineAndPointFormatter());
Replacing Float.NaN with any finite value fixes the problem. Ideally, NaNs should cause a break in the rendered line. For this dataset, I would expect to see two line segments with a break in between.
I'll see if I can implement my own renderer that does this, but I'm also not clear on the expected behavior of FastXYSeries interface when there are NaNs in the data. If all Y values are NaN, should the RectRegion Y min/max be NaN or null? The latter would simplify some of the code, but I don't know if it's acceptable to have an undefined min/max with a series size() > 0.
At codeLine 146 and 147 in CatmullRomInterpolator.java
int n = series.size() -1; dx = series.getX(n).doubleValue() - series.getX(n-1).doubleValue();
CodeLine 102:
public int size() { return series.size() + 2; }
You override the size of the Series by +2 and then try to access thnull e index at n-1 which is 1 past the end of its bounds. This throws a nullPointer Exception and fails.
This originally was working in my application but now as started failing.
Breakingpoint right before it fails shows Size is 21 but series only has 19 elements. then Element 20 is accessed which fails.
My app uses Android Plot for a simple XY plot (lines).
Just updated to API 28 (targetSdkVersion and compileSdkVersion)
It does not build anymore, see the output:
Warning: com.androidplot.pie.PieRenderer: can't find referenced method 'int save(int)' in library class android.graphics.Canvas
Warning: com.androidplot.ui.LayoutManager: can't find referenced method 'int save(int)' in library class android.graphics.Canvas
Warning: com.androidplot.ui.SeriesRenderer: can't find referenced method 'int save(int)' in library class android.graphics.Canvas
Warning: com.androidplot.ui.widget.TextLabelWidget: can't find referenced method 'int save(int)' in library class android.graphics.Canvas
Warning: com.androidplot.xy.LineAndPointRenderer: can't find referenced method 'int save(int)' in library class android.graphics.Canvas
Warning: com.androidplot.xy.XYGraphWidget: can't find referenced method 'int save(int)' in library class android.graphics.Canvas
In fact Canvas.save(int) has been removed from the SDK in API 28. In was deprecated since 28, now it is fully removed and you should call Canvas.save() instead
08-19 19:59:25.694 4505-4505/com.lightstreamer.simple_demo.android E/AndroidRuntime: FATAL EXCEPTION: main Process: com.lightstreamer.simple_demo.android, PID: 4505 android.view.InflateException: Binary XML file line #46: Binary XML file line #46: Error inflating class com.androidplot.xy.XYPlot Caused by: android.view.InflateException: Binary XML file line #46: Error inflating class com.androidplot.xy.XYPlot Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:430) at android.view.LayoutInflater.createView(LayoutInflater.java:645) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727) at android.view.LayoutInflater.rInflate(LayoutInflater.java:858) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) at android.view.LayoutInflater.rInflate(LayoutInflater.java:861) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) at android.view.LayoutInflater.inflate(LayoutInflater.java:518) at android.view.LayoutInflater.inflate(LayoutInflater.java:426) at com.lightstreamer.simple_demo.android.DetailsFragment.onCreateView(DetailsFragment.java:85) at android.support.v4.app.Fragment.performCreateView(Fragment.java:2343) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419) at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809) at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799) at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367) at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:700) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) Caused by: java.lang.NumberFormatException: For input string: "@2131034204" at java.lang.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1306) at java.lang.Float.parseFloat(Float.java:459) at com.androidplot.util.Configurator.parseFloatAttr(Configurator.java:150) at com.androidplot.util.Configurator.inflateParams(Configurator.java:236) at com.androidplot.util.Configurator.configure(Configurator.java:322) at com.androidplot.util.Configurator.configure(Configurator.java:286) at com.androidplot.Plot.loadAttrs(Plot.java:371) at com.androidplot.Plot.init(Plot.java:316) at com.androidplot.Plot.<init>(Plot.java:249) at com.androidplot.xy.XYPlot.<init>(XYPlot.java:150) at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:430) at android.view.LayoutInflater.createView(LayoutInflater.java:645) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727) at android.view.LayoutInflater.rInflate(LayoutInflater.java:858) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) at android.view.LayoutInflater.rInflate(LayoutInflater.java:861) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821) at android.view.LayoutInflater.inflate(LayoutInflater.java:518) at android.view.LayoutInflater.inflate(LayoutInflater.java:426) at com.lightstreamer.simple_demo.android.DetailsFragment.onCreateView(DetailsFragment.java:85) at android.support.v4.app.Fragment.performCreateView(Fragment.java:2343) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419) at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809) at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799) at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367) at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:700) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6121) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
com.lightstreamer.simple_demo.android.DetailsFragment.onCreateView(DetailsFragment.java:85)
this piece of code is a below:
View view = inflater.inflate(R.layout.details_view, container, false);
Please advise...
Thanks in Advance
Hi, how can i draw Stacked bar graph using this library.
how do you assign bugs?
Issue appears to be a missing call to draw vertices in FastLineAndPointRenderer.doOnDrawLegendIcon
Related Stack Overflow question:
http://stackoverflow.com/questions/43530972/scatter-plot-legend-icons-are-blank-when-using-fastlineandpointrenderer
This little square sits to the left of the range axis title.
Is there an option to remove it please ?
The canvas
parameter of the onDraw
method can be null
therefore it should be checked before attempting to draw the chart. In the case below, the app is crashing when the background rendering task that is printing charts in PDF is canceled before views are fully rendered and the cause of that crash is traced to the onDraw method.
06-12 12:39:43.814 18988-19253/my.domain.myapp E/com.androidplot.Plot: Exception while rendering Plot.
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int, android.graphics.PorterDuff$Mode)' on a null object reference
at com.androidplot.Plot.renderOnCanvas(Plot.java:817)
at com.androidplot.Plot$1.run(Plot.java:390)
at java.lang.Thread.run(Thread.java:818)
06-12 12:39:43.817 18988-19252/my.domain.myapp E/com.androidplot.Plot: Exception while rendering Plot.
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int, android.graphics.PorterDuff$Mode)' on a null object reference
at com.androidplot.Plot.renderOnCanvas(Plot.java:817)
at com.androidplot.Plot$1.run(Plot.java:390)
at java.lang.Thread.run(Thread.java:818)
06-12 12:39:43.836 18988-19254/my.domain.myapp E/com.androidplot.Plot: Exception while rendering Plot.
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int, android.graphics.PorterDuff$Mode)' on a null object reference
at com.androidplot.Plot.renderOnCanvas(Plot.java:817)
at com.androidplot.Plot$1.run(Plot.java:390)
at java.lang.Thread.run(Thread.java:818)
'
Hello,
XYLegendWidget
Issue: If you have, say, 5 SeriesBundle with 2 legendenabled==false it
shows 3 legends and 2 empty cells, which is wasted space.Row 191
int nWithoutLegend = plot.getRegistry().getSeriesList().size() -
plot.getRegistry().getLegendEnabledItems().size();
seriesCount -= nWithoutLegend;as quick fix works for me.
Thanks
As suggested here I used null values in yVals for generating a new series:
XYSeries series1 = new SimpleXYSeries(xVals, yVals, "f(x) = tan(x)");
This seems to throw an NullPointerException in LineAndPointRenderer.java, but the app does not crash (caught somewhere?).
java.lang.NullPointerException: Attempt to read from field 'float android.graphics.PointF.x' on a null object reference
at com.androidplot.xy.LineAndPointRenderer.renderPoints(LineAndPointRenderer.java:252)
at com.androidplot.xy.LineAndPointRenderer.drawSeries(LineAndPointRenderer.java:218)
at com.androidplot.xy.LineAndPointRenderer.onRender(LineAndPointRenderer.java:67)
at com.androidplot.xy.LineAndPointRenderer.onRender(LineAndPointRenderer.java:40)
at com.androidplot.ui.SeriesRenderer.render(SeriesRenderer.java:59)
at com.androidplot.xy.XYGraphWidget.drawData(XYGraphWidget.java:814)
at com.androidplot.xy.XYGraphWidget.doOnDraw(XYGraphWidget.java:505)
at com.androidplot.ui.widget.Widget.draw(Widget.java:357)
at com.androidplot.ui.LayoutManager.draw(LayoutManager.java:108)
at com.androidplot.Plot.renderOnCanvas(Plot.java:822)
at com.androidplot.Plot.onDraw(Plot.java:794)
at android.view.View.draw(View.java:16435)
at android.view.View.buildDrawingCacheImpl(View.java:15700)
at android.view.View.buildDrawingCache(View.java:15554)
at android.view.View.draw(View.java:16182)
at android.view.ViewGroup.drawChild(ViewGroup.java:3735)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3525)
at android.view.View.updateDisplayListIfDirty(View.java:15380)
at android.view.View.draw(View.java:16189)
at android.view.ViewGroup.drawChild(ViewGroup.java:3735)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3525)
at android.view.View.updateDisplayListIfDirty(View.java:15380)
at android.view.View.draw(View.java:16189)
at android.view.ViewGroup.drawChild(ViewGroup.java:3735)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3525)
at android.view.View.updateDisplayListIfDirty(View.java:15380)
at android.view.View.draw(View.java:16189)
at android.view.ViewGroup.drawChild(ViewGroup.java:3735)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3525)
at com.android.internal.policy.PhoneWindow$DecorView.dispatchDraw(PhoneWindow.java:2754)
at android.view.View.draw(View.java:16447)
at com.android.internal.policy.PhoneWindow$DecorView.draw(PhoneWindow.java:2740)
at android.view.View.updateDisplayListIfDirty(View.java:15388)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:286)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:292)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:327)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:3040)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2844)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2456)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1341)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6818)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:894)
at android.view.Choreographer.doCallbacks(Choreographer.java:696)
at android.view.Choreographer.doFrame(Choreographer.java:631)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:880)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5728)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
When rendering just one series, this seems to be no problem at all. But when trying to render a second after such error, the second series is not drawn (even the label of the first one isn't drawn).
For my application I need a plotting library that can plot mathematical functions, so I tried the FXPlotExample from your demoapp folder and modified it to display tan(x)
.
This is my complete code (modification to the example start at bottom, indicated by comment):
package com.androidplot.demos;
import android.app.*;
import android.graphics.*;
import android.os.*;
import com.androidplot.util.*;
import com.androidplot.xy.*;
import java.text.*;
import java.util.*;
/**
* A simple XYPlot
*/
public class FXPlotExampleActivity extends Activity {
private XYPlot plot;
/**
* Custom line label renderer that highlights origin labels
*/
class MyLineLabelRenderer extends XYGraphWidget.LineLabelRenderer {
@Override
protected void drawLabel(Canvas canvas, String text, Paint paint,
float x, float y, boolean isOrigin) {
if(isOrigin) {
// make the origin labels red:
final Paint originPaint = new Paint(paint);
originPaint.setColor(Color.RED);
super.drawLabel(canvas, text, originPaint, x, y , isOrigin);
} else {
super.drawLabel(canvas, text, paint, x, y , isOrigin);
}
}
}
/**
* Draws every other tick label and renders text in gray instead of white.
*/
class MySecondaryLabelRenderer extends MyLineLabelRenderer {
@Override
public void drawLabel(Canvas canvas, XYGraphWidget.LineLabelStyle style,
Number val, float x, float y, boolean isOrigin) {
if(val.doubleValue() % 2 == 0) {
final Paint paint = style.getPaint();
if(!isOrigin) {
paint.setColor(Color.GRAY);
}
super.drawLabel(canvas, style, val, x, y, isOrigin);
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fx_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
plot.setDomainStep(StepMode.INCREMENT_BY_VAL, 1);
plot.setRangeStep(StepMode.INCREMENT_BY_VAL, 1);
plot.centerOnDomainOrigin(0);
plot.centerOnRangeOrigin(0);
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
LineAndPointFormatter series1Format =
new LineAndPointFormatter(this, R.xml.line_point_formatter);
// use our custom renderer to make origin labels red
plot.getGraph().setLineLabelRenderer(XYGraphWidget.Edge.BOTTOM, new MyLineLabelRenderer());
plot.getGraph().setLineLabelRenderer(XYGraphWidget.Edge.LEFT, new MyLineLabelRenderer());
// skip every other line for top and right edge labels
plot.getGraph().setLineLabelRenderer(XYGraphWidget.Edge.RIGHT, new MySecondaryLabelRenderer());
plot.getGraph().setLineLabelRenderer(XYGraphWidget.Edge.TOP, new MySecondaryLabelRenderer());
// don't show decimal places for top and right edge labels
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.TOP).setFormat(new DecimalFormat("0"));
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.RIGHT).setFormat(new DecimalFormat("0"));
// create a dash effect for domain and range grid lines:
DashPathEffect dashFx = new DashPathEffect(
new float[] {PixelUtils.dpToPix(3), PixelUtils.dpToPix(3)}, 0);
plot.getGraph().getDomainGridLinePaint().setPathEffect(dashFx);
plot.getGraph().getRangeGridLinePaint().setPathEffect(dashFx);
//----------------------------------------------------------------------------------------------------------
/// modifications starting here:
//----------------------------------------------------------------------------------------------------------
// add a new series' to the xyplot:
plot.setRangeBoundaries(-10, 10, BoundaryMode.FIXED);
plot.addSeries(generateSeries(-5, 5, 300), series1Format);
plot.addSeries(generateSeries1(-5, 5, 10), series1Format);
}
protected XYSeries generateSeries(double minX, double maxX, double resolution) {
final double range = maxX - minX;
final double step = range / resolution;
List<Number> xVals = new ArrayList<>();
List<Number> yVals = new ArrayList<>();
double x = minX;
while (x <= maxX) {
xVals.add(x);
double value = fx(x);
if (value >= -15 && value <= 15)
yVals.add(value);
else
yVals.add(null);
x +=step;
}
return new SimpleXYSeries(xVals, yVals, "f(x) = tan(x)");
}
protected XYSeries generateSeries1(double minX, double maxX, double resolution) {
final double range = maxX - minX;
final double step = range / resolution;
List<Number> xVals = new ArrayList<>();
List<Number> yVals = new ArrayList<>();
double x = minX;
while (x <= maxX) {
xVals.add(x);
yVals.add(x);
x +=step;
}
return new SimpleXYSeries(xVals, yVals, "g(x) = x");
}
protected double fx(double x) {
return Math.tan(x);
}
}
For a quick fix I changed the rendering order, so that the "problematic" series is second:
plot.addSeries(generateSeries1(-5, 5, 10), series1Format);
plot.addSeries(generateSeries(-5, 5, 300), series1Format);
Now they are both plotted, but the labels are still missing.
The proper fix would be to check for null in LineAndPointRenderer.java:
@@ -246,6 +246,8 @@ public class LineAndPointRenderer<FormatterType extends LineAndPointFormatter> e
final PointLabeler pointLabeler = hasPointLabelFormatter ? formatter.getPointLabeler() : null;
for(int i = iStart; i < iEnd; i++) {
PointF p = points.get(i);
+ if (p == null)
+ continue;
// if vertexPaint is available, draw vertex:
if (vertexPaint != null) {
This way it seems to work as expected.
If this fix does not conflict with any other use cases, please consider to add it to the project!
setDrawRangeOriginEnabled and setDrawDomainOriginEnabled are both without effect in AP 1.1.0. The values set are never read.
I set an onTouchListener on the XYPlot to hide my LinearLayout with buttons (let's call it controlPanel) so there would be more space for the graph, but once the controlPanel is gone, the plot fills the new available height and yet the graph stays at the same size. Please look at the screens and you'll know what my issue is. I tried calling plot.redraw() and plot.getGraph.refreshLayout() after changing controlPanel's visibility but to no effect. The graph resizes itself correctly when I make the controlPanel gone and change orientation and viceversa (of course I'm saving the controlPanel's state to keep the visibility status).
If you have a PanZoom on a plot in a ScrollView, they don't play too nicely together. You can pan for half an inch or so, but once you reach the limit where the scrollview would normall scroll, it does so, and the plot stops panning. It kinda works, and it could be worse, but it'd be a lot nicer if the graph panned when you dragged on the plot itself (as opposed to the legend, perhaps), and it the graph couldn't pan further in that direction, the scrollview scrolled instead.
When I do :
implementation 'com.androidplot:androidplot-core:1.5.6'
With:
Android Studio 3.3 Canary 6
Build #AI-182.3684.101.33.4954005, built on August 15, 2018
JRE: 1.8.0_152-release-1136-b06 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0
I can't compile :
Android resource compilation failed
C:\Users\Pascal\Desktop\PalIrri\palIrri\build\intermediates\incremental\mergeDebugResources\merged.dir\values\values.xml:4758: error: duplicate value for resource 'attr/backgroundColor' with config ''.
C:\Users\Pascal\Desktop\PalIrri\palIrri\build\intermediates\incremental\mergeDebugResources\merged.dir\values\values.xml:4758: error: resource previously defined here.
When I have series with differing numbers of points, I get null pointer exceptions (and correspondingly glitchy graphics) when I try to zoom in.
E/com.androidplot.Plot: Exception while rendering Plot.
java.lang.NullPointerException: Attempt to read from field 'float android.graphics.PointF.x' on a null object reference
at com.androidplot.xy.LineAndPointRenderer.renderPoints(LineAndPointRenderer.java:225)
at com.androidplot.xy.LineAndPointRenderer.drawSeries(LineAndPointRenderer.java:190)
at com.androidplot.xy.LineAndPointRenderer.onRender(LineAndPointRenderer.java:50)
at com.androidplot.xy.LineAndPointRenderer.onRender(LineAndPointRenderer.java:37)
at com.androidplot.ui.SeriesRenderer.render(SeriesRenderer.java:59)
at com.androidplot.xy.XYGraphWidget.drawData(XYGraphWidget.java:769)
at com.androidplot.xy.XYGraphWidget.doOnDraw(XYGraphWidget.java:458)
at com.androidplot.ui.widget.Widget.draw(Widget.java:347)
at com.androidplot.ui.LayoutManager.draw(LayoutManager.java:109)
at com.androidplot.Plot.renderOnCanvas(Plot.java:822)
at com.androidplot.Plot$1.run(Plot.java:390)
at java.lang.Thread.run(Thread.java:818)
Note that when I put a breakpoint there, conditional on p == null, inspecting points
shows no nulls, which leads me to suspect threading issues. On the other hand, I've put a breakpoint before the loop, and even inspecting points
each time it stops there (each time showing no nulls) somehow I still get null pointer exceptions, which leads me to suspect debugger inconsistencies.
Hello
Your library looks great !
I just noticed that calling the SimpleXYSeries.resize() throws a NullPointerException if the serie is using Y_VALS_ONLY format.
I would be neat if resize() would work also with Y_VALS_ONLY series.
Cheers
Mathias
When using a FastXYSeries
on a plot with fixed domain boundaries but auto range boundaries, the bounds are incorrectly calculated in SeriesUtils
.
Below is a modified version of SimpleXYPlotActivity
which demonstrates the issue.
package com.androidplot.demos;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.FastXYSeries;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.RectRegion;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;
import com.google.common.math.Stats;
import java.text.DecimalFormat;
import java.util.ArrayList;
/**
* A simple XYPlot
*/
public class SimpleXYPlotActivity extends Activity {
private XYPlot plot;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_xy_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
// create a couple arrays of y-values to plot:
final ArrayList<Integer> times = new ArrayList<>();
final ArrayList<Integer> values = new ArrayList<>();
for (int i = 0; i < 10; i++) {
times.add(i);
values.add(2 * i);
}
FastXYSeries fastXYSeries = new FastXYSeries(){
@Override
public int size() {
return times.size();
}
@Override
public Number getX(int index) {
return times.get(index);
}
@Override
public Number getY(int index) {
return values.get(index);
}
@Override
public String getTitle() {
return "Isaac's crazy thing";
}
@Override
public RectRegion minMax() {
Stats yStats = Stats.of(values);
return new RectRegion(
times.get(0),
times.get(times.size() - 1),
yStats.min(),
yStats.max()
);
}
};
// add a new series' to the xyplot:
plot.addSeries(fastXYSeries, new LineAndPointFormatter(Color.RED, Color.BLUE, null, null));
plot.setDomainLowerBoundary(5, BoundaryMode.FIXED);
plot.setDomainUpperBoundary(9, BoundaryMode.FIXED);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new DecimalFormat());
}
}
SeriesUtils.minMax
will return bounds with a minimum Y and maximum Y both set to the maxY or the series.
public static RectRegion minMax(XYConstraints constraints, XYSeries... seriesArray) {
final RectRegion bounds = new RectRegion();
// make sure there is series data to iterate over:
if (seriesArray != null && seriesArray.length > 0) {
// iterate over each series
for (XYSeries series : seriesArray) {
// if this is an advanced xy series then minMax have already been calculated for us:
if(series instanceof FastXYSeries) {
final RectRegion seriesBounds = ((FastXYSeries) series).minMax();
if (seriesBounds == null) {
continue;
}
if(constraints == null) {
bounds.union(seriesBounds);
} else {
//the following condition will be false
if (constraints.contains(seriesBounds.getMinX(), seriesBounds.getMinY())) {
bounds.union(seriesBounds.getMinX(), seriesBounds.getMinY());
}
//the following condition will be true
if (constraints.contains(seriesBounds.getMaxX(), seriesBounds.getMaxY())) {
bounds.union(seriesBounds.getMaxX(), seriesBounds.getMaxY());
}
}
} else if (series.size() > 0) {
for (int i = 0; i < series.size(); i++) {
final Number xi = series.getX(i);
final Number yi = series.getY(i);
// if constraints have been set, make sure this xy coordinate exists within them:
if (constraints == null || constraints.contains(xi, yi)) {
bounds.union(xi, yi);
}
}
}
}
}
return bounds;
}
I've fixed it by writing a method which constrains the seriesBounds in my fork's branch. I'm not sure this is the right fix though, so I didn't make a pull request. My linked change puts data back on the screen but the y range still includes the full extents of the FastXYSeries instead of the constrained FastXYSeries. I wondered if there shouldn't be a method like Region yMinMax(Number xMin, Number xMax)
to better calculate that or if I should just tell my implementations of FastXYSeries
to consider the current boundary settings while calculating minmax
. Thoughts?
Hey there,
Been using the library for a while to plot fast biosensor data and just interested in optimizing it now.
I notice that when the graph is running, the app keeps using more memory until it quickly hits the garbage collection limit, when it falls back down and keeps climbing. Memory monitor looks like a sawtooth pattern.
With some memory sleuthing, I identified the culprit as being a vast number of Double objects corresponding to the x and y dimensions of my plot. I believe the Doubles are being created by the many doubleValue()
calls in the transform
and length
functions in Region.java
Is there anyway to cut down the number of calls here or convert these Double classes to primitives? I'll be taking a look myself here, but not too familiar with what this class does.
I think this fix could go a long way to making the library more applicable for fast, dynamic graphing
In Androidplot 1.5.1, I got a NumberException with the fillPaintColor set to #00000000 in the code below. It works when the fillPaintColor is set to #000000. A work around is to manually call the setFillPaint method.
LineAndPointFormatter averageFormat = new LineAndPointFormatter(); averageFormat.setPointLabelFormatter(new PointLabelFormatter()); averageFormat.configure(context, R.xml.plot_average_line);
plot_average_line
<?xml version="1.0" encoding="utf-8"?> <config linePaint.strokeWidth="2dp" linePaint.color="@color/IndianRed" vertexPaint.color="@color/IndianRed" vertexPaint.strokeWidth="2dp" fillPaint.color="#00000000"/>
Antroidplot uses two attributes: title and titleTextColor which are already defined in AppCompat library.
This means that you simply cannot use Antroidplot >=1.0 in projects where AppCompat is required.
I can't get to use it in my project . values.xml complains that title and titleTextColor has already been defined
The link posted in the wiki does not work.
How to plot this graph from database instead of static data?
I'm trying to adapt the example to my app but so far I'm getting this error:
Error inflating XML (class com.androidplot.xy.XYPlot): Setter requires param of unsupported type: class com.androidplot.ui.widget.TextLabelWidget
which apparently is a problem with the setContentView( R.layout.activity_graph );
statement in my onCreate()
method. I've created the line_point_formatter_with_labels.xml
resource as described in QuickStart, but can't find any documentation addressing my problem.
Most of the time when I'm looking for some doc about AndroidPlot, an old API doc comes up.
For instance, if you search for BoundaryMode androidplot in Google, you will get the following link first:
http://androidplot.com/javadoc/0.5.1/com/androidplot/xy/BoundaryMode.html
Nothing about the new 1.5.3 version.
Could please tell Google when a page is out of date ?
maybe using the "noindex" metatag
Changing grid insets after the plot has been drawn once do not have effect.
After drawing the plot once
// kotlin
plot.clear()
plot.graph.gridInsets.bottom = PixelUtils.dpToPix(40f)
plot.redraw()
This is because XYGraphWidget onResize is the only place where gridInsets have an effect.
This is called by Widget checkSize which guards calling resize with size of the widget rect. CheckSize is called on widget.draw() But the widget rect does not change due to gridInset being changed.
One quick fix could be to call onResize whenever gridInsets is set.
1.5.4
I've been struggling to get the graph to show up consistently. wrap_content doesn't work, which I guess makes some sense. When I use a scrollview, for when my other views take up too much space, match_parent shrinks the graph to nothing, which also makes some sense. Less sensical is that when I set the graph to be 1138dp wide or wider, the graph doesn't show up at all - there's just a big white empty space the same size as the graph ought to be. Similar things appear to happen for height. I think the specific thresholds may be specific to screen, device, or layout.
In an attempt to get a consistently non-weird size, I've wrapped the graph in a PercentRelativeLayout. Which...I think wasn't working but now apparently is? Not sure I trust it, yet, but it's working for now.
How to disable the domain numbering in android plot ?
heartPulseRateMonitor.setDomainBoundaries(0, 4000, BoundaryMode.FIXED);
heartPulseRateMonitor.getGraph().setDomainCursorPaint(null);
heartPulseRateMonitor.getGraph().setDomainOriginLinePaint(null);
heartPulseRateMonitor.getGraph().setDomainGridLinePaint(null);
I tried all these methods and still the domain boundaries are numbered from 0 to 4000. I am using the latest version of the library. These methods doesn't resolve as well.
heartPulseRateMonitor.getGraphWidget().getDomainTickLabelPaint().setColor(Color.TRANSPARENT);
heartPulseRateMonitor.getGraphWidget().getDomainOriginTickLabelPaint().setColor(Color.TRANSPARENT);
What is the option that I have ?
When chart control is used in listview all elements of the list that include charts are having the same values as the first item although the data is fed correctly.
Once the view is created, I can no longer add series to the plot. This is problematic because I'm asynchronously loading data from a server, and can't add the series until the data gets back.
To be slightly more detailed, if I add series during view creation, they show up fine. If I add series afterwards, however, the plot shows no change.
I was delighted to find that the FastLineAndPointRenderer class had been added, as it increased the fps of a live sensor data plot in my app to a consistent 40-50fps.
However, I've been noticing occasional flickering of the graph, accompanied by index out of bounds exceptions thrown in FastLineAndPointRenderer. I took a look at the code myself and couldn't figure out how to fix it, though.
There's two cases I've noticed that will trigger the flickering:
Here's the relevant part of the error code:
E/com.androidplot.Plot: Exception while rendering Plot.
java.lang.ArrayIndexOutOfBoundsException: length=428; index=428
at com.androidplot.xy.FastLineAndPointRenderer.onRender(FastLineAndPointRenderer.java:73)
at com.androidplot.xy.FastLineAndPointRenderer.onRender(FastLineAndPointRenderer.java:32)
at com.androidplot.ui.SeriesRenderer.render(SeriesRenderer.java:59)
at com.androidplot.xy.XYGraphWidget.drawData(XYGraphWidget.java:760)
at com.androidplot.xy.XYGraphWidget.doOnDraw(XYGraphWidget.java:461)
Hello,
I used androidplot 0.6.0 before and I tried latest 1.4.1 today. I created an empty project and add compile "com.androidplot:androidplot-core:1.4.1". However, I got errors:
\Androidplot-test\app\build\intermediates\res\merged\debug\values\values.xml
Error:(305) Attribute "title" has already been defined
Error:(312) Attribute "titleTextColor" has already been defined
Error:Execution failed for task ':app:processDebugResources'.
com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '\Local\Android\Sdk\build-tools\23.0.3\aapt.exe'' finished with non-zero exit value 1
I'm using androidplot 1.4.1 and I'd like to check all available predefined styles. In the quick start, it uses style="@style/APDefacto.Dark". Where can I see other available styles? Thanks.
One of my users encountered a crash that was caused by androidplot attempting to recycle a null
Bitmap, bgBuffer
. The version of androidplot was 1.5.5.
--------- beginning of crash
E/AndroidRuntime(28933): FATAL EXCEPTION: Androidplot renderThread
E/AndroidRuntime(28933): Process: biz.innomatix.bluefontz, PID: 28933
E/AndroidRuntime(28933): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Bitmap.
recycle()' on a null object reference
E/AndroidRuntime(28933): at com.androidplot.Plot$BufferedCanvas.recycle(Plot.java:240)
E/AndroidRuntime(28933): at com.androidplot.Plot$1.run(Plot.java:422)
E/AndroidRuntime(28933): at java.lang.Thread.run(Thread.java:818)
I haven't looked into the precise conditions that could cause this yet. An easy solution would be to just check for null:
public void recycle() {
if (bgBuffer != null) {
bgBuffer.recycle();
bgBuffer = null;
}
if (fgBuffer != null) {
fgBuffer.recycle();
fgBuffer = null;
}
System.gc();
}
This crash is probably pretty rare, I've never seen it myself while developing and testing.
Hi,
I'm migrating my project from AndroidPlot 0.9.8 to 1.2.2
At some point, I need to set the Y labels width to 0.
I used to it like this : this.plot.getGraph().setRangeTickLabelWidth(0);
How can I do the same with the last version of androidPlot ??
Thanks,
Regards
Mike
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.