I used surfaceview to create a graph. This graph changes continuously over time.
When I use postInvalidate method to update graph, surfaceview is redrawn but I don't want to redraw xy-axis. what should I do?
I believe what you are looking for is the lockCanvas(Rect dirty) method from the SurfaceHolder class.
http://developer.android.com/reference/android/view/SurfaceHolder.html
Official documentation:
"Just like lockCanvas() but allows specification of a dirty rectangle. Every pixel within that rectangle must be written; however pixels outside the dirty rectangle will be preserved by the next call to lockCanvas()."
Therefore you can just change the graphs contents, leaving any pre-drawn axis
Related
In the project I am working on I decided to use SurfaceView instead of a custom double buffered medium. It provides everything I need and it's already double buffered.
The problem is that it wont let me specify multiple dirty rectangles to redraw.
SurfaceView.lockCanvas(Rect) only allows single rectangle and without parameter it's pretty expensive to redraw whole thing. Another solution to call lockCanvas(Rect) for each Rect causes eye-bleeding blinking in the screen, obviously.
Do you have any solution giving the opportunity staying inside Android API field, if not do you have any external alternatives I can use?
If you know the dirty areas before you need to call lockCanvas (sounds like you might), you could calculate a "super rectangle" that locks an area that contains all of your rectangle. For example if your rectangles are (using l,r,t,b coordinates) [0,10,0,20] and [15,30,10,35], your super rectangle would be [0,30,0,35].
I have created glsurfaceview in xml file, I'd like to change X,Y of this glsurfaceView when the button is pressed.
I have onSurfaceChanged() method and there are x,y variables.
can I call this method for chane glsurfaceview position?
if I can, how can I do it, or how can change position?
I have onSurfaceChanged() method and there are x,y variables. can I
call this method for chane glsurfaceview position?
No, you can't, because onSurfaceChanged (GL10 gl, int width, int height) serves as an event. It is called by the OpenGL ES subsystem when your surface size has already changed. Therefore, it is for overriding and performing certain typical operations (as detailed here) when the size of your surface has already changed.
Since GLSurfaceView is a SurfaceView descendant and is part of the View hierachy, you can use the usual positioning methods (such as setX()) to set its position (but don't forget about screen- and density-independence that you should ensure in your Android applications).
As a side note: I don't know your application architecture and details, but when there is a need to re-position a GLSurfaceView, then usually there is an equivalent solution/workaround to the same problem that doesn't require repositioning.
I am setting up a game loop. The loop is set to update at 50 FPS. Currently the only action the app does is draw screen coordinates on response to touch events. Originally I set up the draw function to only draw new touch events. This caused the text to blink. Multiple touch events blink at different times, which leads me to think that Canvas uses multiple pages behind the scenes. In an effort to get around this I made a list of every touch event that happened and on every draw call I redraw the entire list.
Please correct me if I am wrong, the lockCanvas()/unlockCanvasAndPost() calls are in essence a backbuffer swap. Reading the documentation on locking and unlocking it sounds like it is necessary to redraw the entire scene between calls unless you use lockCanvas(Rect dirty). In this case the dirty rect area needs to be redraw while the outside area is preserved.
The content of the Surface is never preserved between unlockCanvas()
and lockCanvas(), for this reason, every pixel within the Surface area
must be written. The only exception to this rule is when a dirty
rectangle is specified, in which case, non-dirty pixels will be
preserved.
I know it sounds like I've answered my own question, but according to the documentation the Surface is never preserved between calls. However this does not explain the behavior of my first implementation, which was I would tap the screen and the text would start blinking. Since I only drew the text one time, this would mean that the blinking is from swapping to the "backbuffer" which didn't get the drawText() call, and the original Surface which did not get destroyed but perhaps it is to be considered unreliable.
So, the question: Do I need to redraw all objects on each draw call? And if so, do I need to "clear" the canvas, or at the least redraw the background image also?
yes, unless you're doing a dirty redraw where you define the region that you are redrawing, every point on your canvas gets destroyed.
How do I call onDraw() on my class extending GLSurfaceView. I need the canvas for drawing the gestures of the user. (FingerPaint.java logic). Mean while I need the onDrawFrame() of the renderer to be called for other effects. I can manage the calls to both the methods by maintaing a flag. I am calling invalidate() but that too is not able to call the onDraw(). GLSurfaceView extends View so I thought I can override onDraw() and can call it by calling invalidate(). Please Throw some light. Thanks in Advance Krishna :)
Try calling requestRender () from your GLSurfaceView.
Obviously this works best when setting rendermode to "RENDERMODE_WHEN_DIRTY".
And that means you won't be rendering continuously, so that may interfere with the "constant" rendering required for your effects.
I think the best solution would be to split the rendering up between 2 overlaying surfaces and 2 renderers. Request the bottom surface (fingerpaint surface) to render a frame whenever the user interacts, and on the top one (gfx surface) you render continuously. Or swap this around... whatever works best.
Just call invalidate() and onDraw() will be called, just like normal View. The canvas is drawn on top of the GLES viewport.
So far I couldn't implement invalidate(Rect dirty). The whole view is redrawn always.
It is needed to put setWillNotDraw(false) before drawing.
I'm developing chess game for Android (androidchess.appspot.com). If I want to add animations, should I use custom View extending Canvas (I do this now), or custom View extending SurfaceView?
I haven't tried using a View to extend Canvas, but for my game I'm using the same method as the LunarLander example game:
public class CustomView extends SurfaceView implements SurfaceHolder.Callback
The usefulness of this is that it gives you handles for SurfaceHolder (so you can call up the canvas which is drawn to the screen), and the callbacks for surfaceCreated, surfaceChanged and surfaceDestroyed. That lets you do things like drawing a custom animation as soon as the surface is available or make sure that you don't try to draw to the canvas after it has been deactivated. Looking through LunarLander should show you how to use these properly.
Edit: I remembered another reason why using a SurfaceHolder was useful. This is because, as I mentioned above, it lets you get direct access to the canvas which is drawn to the screen. With a SurfaceHolder this is done not by overriding onDraw but by using something like Canvas canvas = mSurfaceHolder.lockCanvas(). (See LunarLander for exact syntax). The reason this is important is because it lets you control exactly when the drawing happens. If you can only work by overriding onDraw(), then the drawing doesn't happen until your program reaches a 'waiting' phase. In other words, you can't use invalidate() and onDraw() in a loop because the drawing won't happen until the loop finishes. And since you're likely to use loops for things like drawing a piece moving across the screen, this becomes a problem.
Note: It may be possible to avoid this problem by using multiple threads. I simply haven't tried that since it isn't required for my game; the only animation is has is fixed-length animations in response to user input rather than something continuously moving in the background, so I haven't experimented with multiple threads yet.