Androidplot 0.6.0 Preview

1,271 views
Skip to first unread message

Nick

unread,
Jul 4, 2013, 1:50:31 AM7/4/13
to
Due to the scope of these changes I wanted to give a quick head's up on what's coming in 0.6.0, along with a link to the latest development builds for those who are interested in checking them out.  I'll be updating this thread as things develop.

latest source: https://bitbucket.org/androidplot/androidplot/src
latest jars / demo app: https://androidplot.jira.com/builds/browse/ANDROIDPLOT-TRUNK/latest/artifact/

Notable Changes:
  • TitleWidget, DomainLabelWidget, RangeLabelWidget and UserTextLabelWidget are all gone.  Their functionality has been rolled into the previously abstract TextLabelWidget.
  • LayoutManager is no longer used for the x/y positioning of Widgets; instead each Widget is responsible for it's own positioning and thus LayoutManager.position(...) methods are now available as Widget.position(...) methods.
  • Debug level logging statements have been sprinkled through the library to help with development of both the core library and applications using Androidplot.  These logging statements can be removed with the help of Proguard; the DemoApp provides an example of how this is done.
  • Support for XML configuration of Plots via the Configurator has been cleaned up and and is now being used by the DemoApp to provide better examples for how to create production quality applications using Androidplot which will use appropriate graphical dimensions for the device on which the application is running.
  • Two argument constructors for Formatter instances taking a Context and an int representing an xml resource have been removed.  Replacing it is a configure(Context, int) method exposed from the Formatter base class which can be used to configure any derived class from XML.  See SimplePieChartActivity or SimpleXYPlotActivity for a functioning reference implementation.
  • Removed all deprecated classes and methods

July 4th Update:
  • We refactored Plot and SimpleXYSeries code as a result of some investigations into realtime plotting performance issues.  The bad news is that in some cases this fix will initially reduce application performance, possibly to the point of causing application crashes.  The good news is that implementing a slightly different design (See OrientationSensorExample's usage of Redrawer for a reference) will significantly increase performance over previous Androidplot releases; we are seeing performance increases of 20-30x and higher in situations dealing with large sample sets (100+ points) being updated at higher frequencies (20+hz).

Nick

unread,
Jun 25, 2013, 12:01:15 AM6/25/13
to andro...@googlegroups.com
Quick example of how XML configuration can be used in 0.6.0 using the DemoApp's SimpleXYPlotActivity:

res/layout/simple_xy_plot_example.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
             
style="@style/sample_activity">


   
<com.androidplot.xy.XYPlot
           
android:id="@+id/mySimpleXYPlot"
           
android:layout_width="fill_parent"
           
android:layout_height="fill_parent"
           
androidPlot.title="A Simple XY Plot"
           
androidPlot.domainLabel="Domain"
           
androidPlot.rangeLabel="Range"
           
androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"
           
androidPlot.domainLabelWidget.labelPaint.textSize="@dimen/domain_label_font_size"
           
androidPlot.rangeLabelWidget.labelPaint.textSize="@dimen/range_label_font_size"
           
androidPlot.graphWidget.marginTop="20dp"
           
androidPlot.graphWidget.marginLeft="15dp"
           
androidPlot.graphWidget.marginBottom="25dp"
           
androidPlot.graphWidget.marginRight="10dp"
           
androidPlot.graphWidget.rangeLabelPaint.textSize="@dimen/range_tick_label_font_size"
           
androidPlot.graphWidget.rangeOriginLabelPaint.textSize="@dimen/range_tick_label_font_size"
           
androidPlot.graphWidget.domainLabelPaint.textSize="@dimen/domain_tick_label_font_size"
           
androidPlot.graphWidget.domainOriginLabelPaint.textSize="@dimen/domain_tick_label_font_size"
           
androidPlot.legendWidget.textPaint.textSize="@dimen/legend_text_font_size"
           
androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
           
androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
           
androidPlot.legendWidget.heightMetric.value="25dp"
           
androidPlot.legendWidget.positionMetrics.anchor="right_bottom"
           
androidPlot.graphWidget.gridLinePaint.color="#000000"/>
</LinearLayout>

res/values/dimens.xml (developers can provide display specific settings via res/values-hdpi etc.)

<?xml version="1.0" encoding="utf-8"?>
<resources>
   
<dimen name="activity_horizontal_margin">16dp</dimen>
   
<dimen name="activity_vertical_margin">16dp</dimen>
   
<dimen name="pie_segment_label_font_size">10dp</dimen>
   
<dimen name="title_font_size">20dp</dimen>
   
<dimen name="domain_label_font_size">13dp</dimen>
   
<dimen name="range_label_font_size">13dp</dimen>
   
<dimen name="range_tick_label_font_size">15dp</dimen>
   
<dimen name="domain_tick_label_font_size">15dp</dimen>
   
<dimen name="legend_text_font_size">20dp</dimen>
</resources>

res/xml/line_point_formatter_with_plf1:

<?xml version="1.0" encoding="utf-8"?>
<config
       
linePaint.strokeWidth="3dp"
       
linePaint.color="#00AA00"
       
vertexPaint.color="#007700"
       
fillPaint.color="#00000000"
       
pointLabelFormatter.textPaint.color="#FFFFFF"/>

res/xml/line_point_formatter_with_plf2:

<?xml version="1.0" encoding="utf-8"?>
<config
       
linePaint.strokeWidth="3dp"
       
linePaint.color="#0000AA"
       
vertexPaint.color="#000077"
       
fillPaint.color="#00000000"
       
pointLabelFormatter.textPaint.color="#FFFFFF"/>

SimpleXYPlotActivity.java:

package com.androidplot.demos;
import android.app.Activity;
import android.os.Bundle;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYSeries;
import com.androidplot.xy.*;
import java.util.Arrays;


/**
 * A straightforward example of using AndroidPlot to plot some data.
 */

public class SimpleXYPlotActivity extends Activity
{


   
private XYPlot mySimpleXYPlot;


   
@Override
   
public void onCreate(Bundle savedInstanceState)
   
{
       
super.onCreate(savedInstanceState);
        setContentView
(R.layout.simple_xy_plot_example);


       
// initialize our XYPlot reference:
        mySimpleXYPlot
= (XYPlot) findViewById(R.id.mySimpleXYPlot);


       
// Create a couple arrays of y-values to plot:
       
Number[] series1Numbers = {1, 8, 5, 2, 7, 4};
       
Number[] series2Numbers = {4, 6, 3, 8, 2, 10};


       
// Turn the above arrays into XYSeries':
       
XYSeries series1 = new SimpleXYSeries(
               
Arrays.asList(series1Numbers),          // SimpleXYSeries takes a List so turn our array into a List
               
SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, // Y_VALS_ONLY means use the element index as the x value
               
"Series1");                             // Set the display title of the series


       
// same as above
       
XYSeries series2 = new SimpleXYSeries(Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");


       
// Create a formatter to use for drawing a series using LineAndPointRenderer
       
// and configure it from xml:
       
LineAndPointFormatter series1Format = new LineAndPointFormatter();
        series1Format
.setPointLabelFormatter(new PointLabelFormatter());
        series1Format
.configure(getApplicationContext(),
                R
.xml.line_point_formatter_with_plf1);


       
// add a new series' to the xyplot:
        mySimpleXYPlot
.addSeries(series1, series1Format);


       
// same as above:
       
LineAndPointFormatter series2Format = new LineAndPointFormatter();
        series2Format
.setPointLabelFormatter(new PointLabelFormatter());
        series2Format
.configure(getApplicationContext(),
                R
.xml.line_point_formatter_with_plf2);
        mySimpleXYPlot
.addSeries(series2, series2Format);


       
// reduce the number of range labels
        mySimpleXYPlot
.setTicksPerRangeLabel(3);
   
}
}

Nick

unread,
Jun 25, 2013, 12:06:15 AM6/25/13
to andro...@googlegroups.com
Screenshot of the result:


Ken Yee

unread,
Jun 28, 2013, 4:22:14 PM6/28/13
to andro...@googlegroups.com
Any chance we'll see cubic (smoothed) line charts?

Would help if the examples were prettier looking too (IMHO).  I know...sounds vain, but that's what people look at ;-)

thanks,

 ken

Nick

unread,
Jun 28, 2013, 5:01:49 PM6/28/13
to andro...@googlegroups.com
Hey Ken,

It's fairly straightforward to render a Path using cubicTo(...) that looks nice.  In fact there is at least one popular competitor to Androidplot that will remain unnamed that uses this method.  The problem is that the displayed line does not actually pass through the points of the plot and to add insult to injury the margin of error can vary for every point in the line. I had shelved the BezierLineAndPointRender implementation indefinitely after hitting a dead end with using Path.cubicTo(...) to draw smooth-but-accurate paths.  I knew that it was theoretically possible to approximate a Catmull-Rom spline using cubic beziers but that's about all I knew. So I posted this question on StackOverflow which went unanswered for about 2 years.  

So that's the back story. If you check out the SOF thread mentioned above, you'll notice that there is a new answer citing a Javascript implementation.  I've only briefly looked at it, but I didnt see any red flags in terms of porting to an Android implementation using Path's methods.  As far as getting that into 0.6.0 - It's unlikely at this point since that's probably going to be released in the next couple of days.  0.6.1 though, barring any unforseen issues with it's implementation, I'd say very likely.  My best guess on a timeframe to expect 0.6.1 is ~30-45 days from today.  If you're interested in taking a crack at implementing it yourself I'd be more than happy to work with you to get your environment setup and answer any questions you might have in the process.

Regarding your more general point about the visual quality of the Androidplot samples - I'm with you 100%. That's actually my one remaining goal before kicking 0.6.0 out the door: improve the DemoApp aesthetics.  It's really a shame that this has not been done until now because Androidplot is capable of significantly more than what the samples show.

SuperJugy

unread,
Jul 4, 2013, 5:02:58 PM7/4/13
to andro...@googlegroups.com
Hey Nick, does this redrawer change affects the new XYPlotZoomPan function? since basically every touch event tells the plot to redraw. or is this a completely different thing?

SuperJugy

Nick

unread,
Jul 4, 2013, 5:06:46 PM7/4/13
to andro...@googlegroups.com
It could but probably wont in any noticeable way; I tested with the preexisting pan/zoom sample in the DemoApp and it is performing well without any changes.  I think the only people who should experience any kind of noticeable change are those that have data regularly coming into their app at a relatively high frequency.

Nick

SuperJugy

unread,
Jul 4, 2013, 5:10:44 PM7/4/13
to andro...@googlegroups.com
And would there be any point in using the redrawer in the XYPlotZoomPan class? I mean, would it help performance? cause in my app I use static data but it is somewhat high like 500 points or something, but the zooming and panning makes it redraw. if it is no problem for static data or there is no performance gain, I'll leave it as is.

SuperJugy

Nick

unread,
Jul 4, 2013, 5:28:49 PM7/4/13
to
Probably not since the changes are in response to intermittent touch events.  If the touch events are coming in at a very fast rate then I'd change my answer to *maybe*.  The source of the performance problem is that even in the case of rendering with background threads there are synchronized sections being entered by the thread calling redraw().  Under the right conditions that synchronization will cause the calling thread to momentarily halt while it waits to acquire the mutex.  There are a range of side effects this can have on performance, depending on where the data is coming from, how (or even if) its buffered, if the input is continuous or intermittent, etc.

Andy Powell

unread,
Jul 5, 2013, 6:02:48 PM7/5/13
to andro...@googlegroups.com
I've recently decided to stop using GraphView and move to using AndroidPlot. While it was trivial to use GraphView no longer fits my needs. Anyway I'm not entirely sure if what I have are bugs in 0.6.0 or just my understanding of how AndroidPlot works. I'm also not entirely sure if this is the place to ask this.

I've attached an image which highlights the issues, all are somewhat related

The red and yellow boxed areas show where I have changed the size of the domain and range labels using

        graph.getGraphWidget().getDomainLabelPaint().setTextSize(25);

        graph.getGraphWidget().getRangeLabelPaint().setTextSize(25);

As you can see the yellow boxed labels are cut in half and the red boxed labels, while they look 'correct' are in fact missin a proceeding 2 - - they are temperatures and range from 23.1 to 27.4

Having set the domain and range label sizes the third issue pops up, the first two labels are smaller than the rest - looks like they are basically the original size.

Are these three issues bugs in the new version or just my poor understanding of AndroidPlot?

Thanks

Andy

androidplot2.png

Nick

unread,
Jul 5, 2013, 6:16:07 PM7/5/13
to
Hi Andy - thanks for giving us a try :)

Regarding the clipped text - that is due to the default margins on the GraphWidget.  You should be able to correct both by using:

plot.getGraphWidget().setMarginLeft(100); // or whatever value you determine works for your setup
plot
.getGraphWidget().setMarginBottom(100); // same as above

It's worth noting that the above sets the margins in pixels which is bad if you are going for a layout that looks good on multiple screen densities.  Instead, you can either use a dp value by calling

PixelUtils.dpToPix(...)

OR an even better method is to use the Configurator to set these values in your layout.xml so that you can define different params for each screen type.  I've actually been working on updating the DemoApp to use this method so you should be able to look at that source code to get an idea of how that's done.

Regarding the reason why the first two labels are smaller than the rest:  Androidplot uses a different Paint instance for these "origin" elements.  You can get access to them by calling:

plot.getGraphWidget.getDomainOriginLabelPaint();
plot
.getGraphWidget.getRangeOriginLabelPaint();

Hope that helps,
Nick

Andy Powell

unread,
Jul 6, 2013, 1:00:57 PM7/6/13
to andro...@googlegroups.com
Thanks Nick,

I'll  do some more reading, I haven't has yet found the Configurator.. will dig deeper in the code.

Andy

Nick

unread,
Jul 6, 2013, 1:11:17 PM7/6/13
to andro...@googlegroups.com
It's actually a pretty simple thing - basically it lets you define params in xml and uses reflection to lookup the appropriate setters/getters to set the param for you.  What's nice about it is that because its at the XML level, you can specify stuff in dp etc. and also provide separate configs for tablets, phones, devices of various densities etc.

For example, if you were to add this to your Plot layout xml:

androidPlot.titleWidget.labelPaint.textSize="20dp"



it would be like doing this in the code:

plot.getTitleWidget().getLabelPaint().setTextSize(PixelUtils.dpToPix(20);



It supports configuration of primitives, strings, dimensions,  *most* (some exceptions) enumerations and a few other things I'm not remembering at the moment.

Nick

Nick

unread,
Jul 20, 2013, 4:58:46 PM7/20/13
to andro...@googlegroups.com
Now that 0.6.0 has been officially released I am locking this topic.  Feel free to create a new thread for any new issues.
Reply all
Reply to author
Forward
This conversation is locked
You cannot reply and perform actions on locked conversations.
0 new messages