I have an android app that collects data and I need to graph that data. The dataset could be a few hundred samples, to tens of thousands. The X axis is time. The Y axis can have 1 to 15 different sets of data.
I've looked into some graphing libraries such as achartengine, but they all seem to expect that your graph will have a fairly compact dataset that fits nicely in a screen. With 20k samples, my graph will be much wider than it is tall. Actually I never really want the Y axis taller than the screen, the zoom should zoom only in the X axis.
My ideal interface is basically like a sideways listview that you can just fling left or right to scroll the really wide graph. Zoom will simply compress or expand the time scale.
In any case, my question is what are the best practices when trying to do something like this? I can find graphing tutorials, but nothing that addresses this problem specifically. It would seem very wasteful to try and render the whole graph at once. But I want the slide navigation to be smooth. Will drawing a screen at a time to the canvas be fast enough for a smooth scroll? Or will I have to go to openGL?
Thanks.
I hear users of AChartEngine mentioning that they add tens of thousands of data values in the model and AChartEngine still handles and displays them fine.
Related
I wonder if it is possible to achieve something like this with MPAndroidChart library?
Basically, I want to have multiple line charts with different Y axis stacked vertically sharing the same X axis (when I move, zoom or highlight a value I want them to be synchronized). If I get it right, there is no explicit support for this behavior.
I tried to manipulate the values (set negative ones with offset) of the second dataset and I was able to achieve the desired charts placement. But I couldn't find a way to draw the values correctly on the Y axis (AxisValueFormatter isn't enough because I need alternate granularity).
Now I'm thinking of having multiple charts glued together and synchronized by callbacks and zoom/move/highlight them programmatically. But I fear it may affect the performance since I need to work with thousands of data points.
Any ideas? I may even take a look at other free libraries if they can do it, but I prefer to stick with MPAndroidChart as I have good experience with it.
Imagine emptying a pouch having 100 stamps on a small area. That would be the starting point for my screen. I should be able to scale individual stamps in and out, animate them on a swiping gesture, overlay them and animate them so they all come towards the place of a former stamp that just got swiped out of screen, filling that space in. Plus zooming and panning over the entire screen.
I have made canvas level zooming, panning, and drawing by hand, but I feel this is going to benefit a lot from some kind of library. What should I be looking for ? Math libraries, physics, game engines ?
I don't suppose making these into ImageViews and all together into a ViewGroup and trying to make it work from there would be a good idea.
Thanks
I am using LibGdx to develop a game. For Now I am not using scene2D. I am struck up in increasing the levels of the game as I do not have the scrolling screen.
I like to design a a scrolling screen as it is in many games which are level based (for ref, lets say Candy crush). Could you please point me a example on how to have such a scrolling screen to show a bigger area where I can show many levels.
Thanks is Advance !
Using the Scene2D function is not necessary for this and is more for GUI implementation and different screens. The Scroll pane really shines when creating reading content that does not fit your phone. I do advice to start learning Scene2D to create MenuScreens and UI though.
What Candy Crush "simply" does is having multiple backgrounds that are placed next to each other and tile seamlessly. They use buttons in the correct place for levels. By dragging a finger across the screen the camera will move in that direction. For the movement from one level to the next there is probably something like a spline in play.
It is important only to draw the background tiles and buttons that are actually visible on the screen if you have many. Since these have fixed positions and you know your camera area and position you can calculate what to draw and what not. Just drawing everything each frame is likely to slow down your fps.
You can do a search on:
Tilemaps, for you backgrounds but you probably want them in just one direction so a simple 1D array would suffice.
Dragging, to move your camera. Here I gave a basic explanations on how I do it.
Splines, are a bit tougher and you do not really need them. They could be used to animate or move something along a curve.
Thats all, expecting you know how to create something like a button (click a sprite).
Currently I am doing app allowing user to draw. Simple think, just extend Canvas class and most of the thing is done.
That was my initial thinking and idea. But as the canvas is rather small because this is only what user see on the screen there is not much possible space to draw. Going through documentation I found translate() method allowing me to move canvas. What I did find out is when I move it, there is some kind of blank space just as you would move piece of paper. I understand that this is totally normal, as I've said before - canvas is only "the screen".
My question is - is there a possibility to make something like infinite canvas so you can make a huge painting and move everything around?
Before this question I was thinking about two things how something like this can be done:
Move all objects on canvas simultaneously - bad idea, because if you have a lot of them then the speed of moving is very bad.
Do something similar as it is done in ListView when you move it (or better see on the screen) only views that are on the screen together with one before and one after are loaded to memory and rest is uploaded dynamically when needed. I think this is the best option to achieve this goal.
EDIT:
Question/answer given by Kai showed me that it is worth to edit my question to clarify some of the things.
Basic assumptions about what can be done by user:
User is given opportunity to draw only circles and rectangles with some (around 80%) having drawable (bitmap) on them on canvas.
I assume that on all screens there will be maximum 500-800 rectangles or circles.
First of all thinking about infinity I was thinking about quite big number of screens - at least 30 on zoom 1x in each side. I just need to give my users bigger freedom in what they are doing.
On this screen everything can be done as on normal - draw, scale (TouchListener, ScaleListener, DoubleTapListener). When talking about scaling, there is another thing that has to be concerned and connected with "infinity" of canvas. When user is zooming out then screens, or more precise objects on the invisible "neighbours" should appear with proper scaling as you would zoom out camera in real life.
The other thing that I've just realised is possibility of drawing at small zoom level - that is on two or three screens and then zooming in - I suppose it should cut and recalculate it as a smaller part.
I would like to support devices at least from API 10 and not only high-end.
The question about time is the most crucial. I want everything to be as smooth as possible, so user wouldn't know that new canvas is being created each time.
I think it really depends on a number of things:
The complexity of this "infinite canvas": how "infinite" would it really be, what operations can be done on it, etc
The devices that you want to support
The amount of time/resource you wish to spend on it
If there are really not that many objects/commands to be drawn and you don't plan to support older/lower end phones, then you can get away with just draw everything. The gfx system would do the checking and only draws what would actually be shown, so you only waste some time to send commands pass JNI boundary to the gfx system and the associated rect check.
If you decided that you needs a more efficient method, you can store all the gfx objects' positions in 4 tree structures, so when you search the upper-left/upper-right/lower-left/lower-right "window" that the screen should show, it'll fast to find the gfx objects that intersects this window and then only draw those.
[Edit]
First of all thinking about infinity I was thinking about quite big
number of screens - at least 30 on zoom 1x in each side. I just need
to give my users bigger freedom in what they are doing.
If you just story the relative position of canvas objects, there's practically no limit on the size of your canvas, but may have to provide a button to take users to some point on canvas that they are familiar lest they got themselves lost.
When talking about scaling, there is another thing that has to be
concerned and connected with "infinity" of canvas. When user is
zooming out then screens, or more precise objects on the invisible
"neighbours" should appear with proper scaling as you would zoom out
camera in real life.
If you store canvas objects in a "virtual space", and using a "translation factor" to translate objects from virtual space to screen space then things like zoom-in/out would be quite trivial, something like
screenObj.left=obj.left*transFactor-offsetX;
screenObj.right=obj.right*transFactor-offsetX;
screenObj.top=obj.top*transFactor-offsetY;
screenObj.bottom=obj.bottom*transFactor-offsetY;
//draw screenObj
As an example here's a screenshot of my movie-booking app:
The lower window shows all the seats of a movie theater, and the upper window is a zoomed-in view of the same theater. They are implemented as two instances of the same SurfaceView class, besides user input handling, the only difference is that the upper one applies the above-mentioned "translation factor".
I assume that on all screens there will be maximum 500-800 rectangles
or circles.
It is actually not too bad. Reading your edit, I think a potentially bigger issue would be if an user adds a large number of objects to the same portion of your canvas. Then it wouldn't matter if you only draw the objects that are actually shown and nothing else - you'd still get bad FPS since the GPU's fill-rate is saturated.
So there are actually two potential sources of issues:
Too many draw commands (if drawing everything on canvas instead of just drawing visible ones)
Too many large objects in the same part of the screen (eats up GPU fill-rate)
The two issues requires very different strategy (1st one using tree structures to sort objects, 2nd one using dynamically generated Bitmap cache). Since how users use your app are likely to different than how you envisioned it to be, I would strongly recommend implementing the functions without the above optimizations, try to get as many people as possible to do testing, and then apply optimizations to each of the bottlenecks you encounter until the satisfactory performance is achieved.
[Edit 2]
Actually with just 500~800 objects, you can just calculate the position of all the objects, and then check to see if they are visible on screen, you don't even really need to use some fancy data structures like a tree with its own overheads.
I'm redesigning an analog gauge widget I made a while back, essentially wanting to give it smoother looks and touch interfaces.
Currently I have just three bitmaps, on for the frame of the gauge, on for the ticks and a base that covers 1/3 of the gauge located at the bottom. I use a canvas drawn line for the needle. This gauge works, but doesn't have many of the features that I would like.
What I would like to do is have the ticks be dynamically drawn so it is possible to simulate a pinch based zoom. As the user zooms in the ticks drift apart until there is enough space for a new subset of tick to appear nested in between the larger farther apart ticks. As the user zooms out the tick begin compressing until the smallest tick are forced out become invisible (not drawn). The gauge will also need to register a slide (across the circumference of the gauge) touch to force the gauge to rotate.
The last time I tried to draw each line on a canvas for a gauge, it was incredibly slow was not readable because it flickered so horribly.
So I am wondering if anyone has any idea's, source or tips on how to achieve this gauge. I have spent a good while googling compasses, clock and gauges that may have any or all of the features I want so I can see how others did it, but I can't find anything.
Any help will be appreciated.
~Aedon
I found a fantastic tutorial not only on the gauge, but in genreral android features. Take a look.