I need some help with this simple animation on my Android phone. I'm a newbie with animation and graphics.
I'm graphing accelerometer data as a sliding time series window. As new accelerometer data is read, its data is plotted on the right, pushing previous data to the left, as shown below:
My program is running pretty smoothly, but I would like some help optimizing the animation. Here are my main concerns:
My current implementation reads all the accelerometer data in one thread and keeps the data in a fixed-size FIFO queue to capture the width of the time series window. I then use Timer.scheduleAtFixedRate() to plot out the entire contents of the queue so that the whole graph is re-drawn every 50 milliseconds. Can I improve upon this? Do I really need to re-draw the graph so often like this? In another similar program I've seen, each pixel column is copied to one pixel to the left, rippling down the graph; the newest data's column is drawn on the far-right pixel column. Is this better?
I redraw the legend (in the upper left) in the drawing thread that runs the draw function every 50 milliseconds. Is there any way to "keep" that legend in place instead of having to constantly re-draw it?
Any other help would be appreciated. I have heard of optimizations like double-buffering but am clueless if that would help me.
If the legend and the cross hairs only need to be drawn once, then you should place it into a buffer bitmap. For your graph line maybe try using the Path object to plot the lines. When it gets time to draw the lines just drawLine to the appropriate point and then translate the canvas left appropriately.If
Related
im new to this android things. And i have to develop an application that can help an autism to learn numbers. I have a few ideas and I've been trying to learn and implement the code. But it's failed. The question is how can i apply the motion code or sprite to draw a numbers or letter? For example like this, i wanna make the penguin move through the line and draw a number nine.
There is example from mybringback.com which is the image move to draw a rectangle. How can i implement it to draw a number? Im sorry if i asking too much, i just trying to get some ideas.
I think that you should first build an utility program, in order to create the "path vector".
What I mean by path vector is simply a vector of Points (where a point has x value, and y value). And your utility should let you draw whatever you want, with a simple pen. You should draw on surface and store points when mouse is down, and ignore points when mouse is up.
Then, in the main program, you will just have to read at the path of your number/letter.
I've tried to implement something like this for the Sugar OLPC platform, without serializing path into files : I was able to draw, and to view the animation. And I used the process I've just described you.
Hope it can help you.
P.S : I used the word mouse, but you guessed that I talk about finger ...
There are various ways to achieve animation effects. One approach that is quite versatile involves creating a custom View or SurfaceView in which you Override the onDraw method. Various tutorials can be found on this; the official Android discussion of it is here:
http://developer.android.com/guide/topics/graphics/2d-graphics.html#on-view
Your implementation will look something like this:
// Find elapsed time since previous draw
// Compute new position of drawable/bitmap along figure
// Draw bitmap in appropriate location
// Add line to buffer containing segments of curve drawn so far
// Render all segments in curve buffer
// Take some action to call for the rendering of the next frame (this may be done in another thread)
Obviously a simplification. For a very simplistic tutorial, see here:
http://www.techrepublic.com/blog/software-engineer/bouncing-a-ball-on-androids-canvas/1733/
Note that different implementations of this technique will require different levels of involvement by you; for example, if you use a SurfaceView, you are in charge of calling the onDraw method, whereas subclassing the normal View lets you leave Android in charge of redrawing (at the expense of limiting your ability to draw on a different thread). In this respect, Google remains your friend =]
I would like to draw a slash animation between 2 points that I have already randomly generated.
The animation can be as simple as the line extending to the other point over a set amount of time. I would like the animation to be a "pretty" line so I was using a bunch of images and iterating over them and not just canvas.drawLine(x, y, u, v, paint).
The main issue I am running into is the points are not always the same distance apart or same direction. Im not sure if having a set number of animation sequences would work because of those differences. What is the best way to do this?
Not sure if this has been answered, but you'll have to say how complicated your imagery is. If it's a simple slash line, then drawLine would work. You'll also have to say how you are animating the line, like Android XML or if you are using some sort of timer.
There's so many ways to do this. If it's a simple line, you can use math to increment some coordinates. Watch out for using frame counting, where you say "increment the animation for the frame". It's a quick-and-dirty way to animate, and sometimes will get the job done.
A lot of video games use time-based drawing. "If this amount of time has elapsed since the last draw, draw this much". The result looks much more natural and the same between devices with different amount of horsepower.
There's also what you are drawing on. Are you using a View or a SurfaceView? The list goes on.
I want to draw (4 or 5) real-time charts visualizing a lot of data (a new value every 30ms) within 15 minutes. I am using Path but it seems to work very slowly when I want to display over 20000 values and translate the canvas and it gets worse every second. I also tried using drawLine but it doesn't work fluently at all.
Does anyone have any ideas about a better solution than Path? Or maybe I am doing something wrong? My current solutio is : I initialize the Path in the beginning and then just add a new line to it every time I get a new value, then I translate the canvas.
Displaying a path of 20 000 values will probably be slow whatever you use, even in OpenGL, it's just a lot of data to send to the graphics chip to draw...
The "correct" way to do it (performance-wise) is probably to cache as much stuff as possible, and draw only what needs to be drawn. You could for example draw to a bitmap the first N points, and then only use a path for the next M points (and draw the bitmaps for the previous ones). Drawing a bitmap is pretty fast. So once in a while, you could just refresh your bitmap (which will take a bit more time) and then plot the remaining points.
You could also decide to have a shorter path : do you really need 20 000 values ? Couldn't you be grouping points 5 by 5 or 10 by ten (or even more) ? Currently, the screens are at most 1280 pixels wide anyways...
Are drawing all of that in every onDraw()? That's why it's slow. First of all, nobody can see changes every 30ms. So keep drawing updates into a cache bitmap, then call invalidate(). Then in onDraw() just copy that bitmap onto the canvas.
Drawing over 20000 lines with canvas is going to be slow, no matter what. My bet is that you have to go with openGL on this one. This link might be helpful: http://obviam.net/index.php/opengl-es-with-android-switching-from-canvas-to-opengl/
I am looking for help/resource that will help me in bringing up a image as follows in android view.
Image looks like x-y axis graph, with sawtooth waves along x-axis, this is a static image developed using certain tool.
I need help to make a line move, parallel to y-axis (red in color) that waits at origin(0,0) and starts moving along x axis until the sawtooth wave ends.
3.If you imagine this as image, there is a wave on x axis and a red line that moves across wave, which is the noise generated in android mobile.
Concern: How to overlap a static image (wave+x-y axis) with a dynamic image (red line) and make it move as the code runs.
There is a timer that will generate the noise (mute/unmute microphone) and user gets to see it in screen when these interference occurs.
I thank you for spending time to read my post.
Please let me know if there are any redundant info , I will edit my question.
If you subclass view you can draw whatever you want in the onDraw(). You just need to use the provided Canvas.
I want to draw a graph that updates in real time (grows from the right). The most efficent way I can think of to do that would be to copy everything from x[0 .. width-2] left by 1 pixel, then draw the new value at x[width-1].
I have little experience with Android, but from what I can tell, Canvas doesn't operate on it's contents at all. Do I need to repaint the entire screen each time? This involves scaling and smoothing so I'm worried it will be slow.
Should I draw into a byte[][] then use this to paint to the screen (shifting the contents of my buffer left each time) ?
If your graph is bounded, try rendering all of it once to an Image, and then blit the relevant parts from that Image to your Canvas. Try to avoid actually "moving" pixels in the buffer, as that might introduce dependencies between your reads and writes and could really kill the performance. It might actually be better to copy from 1 buffer to another and alternate which one gets blitted to the screen. Finally, if you end up having to manually work on pixels, make sure you run on the image in lines rather than columns and that you start from the beginning of the line to help with the caching.
Regarding performance, without profiling we cannot say.
It may be that line drawing is hardware accelerated on your target phone, and you should draw the graph from scratch using line-drawing primitives each frame.
On the other hand, the straightforward pixel manipulation of an image buffer would be:
Create an image that is the right size and clear it to a "background_color". This image needs to have setpixel() functionality.
Have an array of values that record the y of each x time, so for any column you know where you last plotted your graph.
Treat this "chart_image" and "chart_array" as a circular buffer. For each time step:
Y = ...;
X = time_since_start % chart_width;
chart_image.setpixel(X,chart_array[X],background_color); // clear previous line
chart_array[X] = Y;
chart_image.setpixel(X,chart_array[X],foreground_color); // draw new plot
And now you need to blit it. You need to blit the image twice:
X = time_since_start % chart_width;
// the newest data is on the left of the chart_image but gets drawn on the right side of the output
blit(out_x+X,out_y, // destination coordinates
chart_image,
0,0, // top left of part of chart_image to blit
X,chart_height); // bottom right of chart_image part
// the oldest data is on the right of the chart_image but gets drawn on the left side of the output
blit(out_x,out_y,
chart_image,
X,0,
chart_width,chart_height);
Things get more tricky if you want to use lines rather than individual pixels, but a drawline() instead of a setpixel() can make that work with this approach too.
(Apologies for not knowing the Android APIs; but the approach is generic.)
Just a thought, which you may have considered already, but I wouldn't shift the contents of the buffer - I'd just try using it like a circular buffer. Keep an index to the current column and once you've wrapped around to the left-most column again you can draw to the destination in two segments - what is on the right side of the current column and then what is to the left, including the most recently filled column. This way you'll not have to shift anything around, and each screen refresh is just two blits (bitmap copies) for the two segments. If that bit's too slow you could still always paint those into a second off-screen buffer before blitting the whole thing to the screen in one go. Surely one large blit to the screen is fairly quick, no?
Since i can take as granted that you are storing the graph data in memory, redrawing it shouldn't be a problem. It's not intensive at all to redraw a set of points every frame. Shifting memory would be intensive, it's moving everything versus just painting only what you need.
Worst case scenario, since it's a function of time, only one value per column of the display, aprox 800 pixels/values in landscape that the system has to draw. It's trivial.
Have you profiled this?
EDIT: Remember, it's not that the system has to draw each point, it only draws on memory, then makes the use of it's primitives. Don't think like it iterates drawing the point, dumping to the video memory, then again.