Can I lay a fixed layer over a custom canvas? - java

In Android Studio, I'm developing a game in which I draw my animation at 60fps using a SurfaceView object. I use a semitransparent image as the top layer to hide the edges of the playing field -- sort of a "fogs of war" effect so that the player does not know what to expect beyond the shadows.
My problem is that I need to draw this shadow image for every frame, even though the shadow never changes or moves, even when the playing field scrolls right/left/up/down. And it's a full-screen image, so it slows the game to a crawl.
Is there a way to create a one-time overlay ONCE on top of the animated custom canvas? I also want to interact with the canvas beneath it, as if the overlay was not even there.

Have you tried putting a full screen ImageView over your surface view and setting the "fog of war" image to this, should draw it once (this is assuming the background to your "fog of war is transparent").
If you need anything fancier then ViewOverlay should cover you, but my understanding is this is used when individual views wish to draw outside their bounds for animations, as you are using full screen surface view this should be unnecessary
https://developer.android.com/reference/android/view/ViewOverlay.html
Also no reason why you can't stick a surface view over a surface view. One for the fog of war / screen effects, one for the game surface.

Based on the response from Thomas Stevens, I researched my options for overlaying my SurfaceView with an ImageView. My solution is to add a FrameLayout that contains the needed ImageView. (That way, I can add additional views to the overlay simply by updating the layout XML.)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//temporarily set the view to the overlay layout to gain access to the frame
setContentView(R.layout.overlay_game);
FrameLayout overlayLayout = (FrameLayout)findViewById(R.id.gameOverlayFrame);
//set the final view to the active game surface (a Java-coded SurfaceView object)
setContentView(new GameSurface(this));
//add the overlay view on top of the game surface view
addContentView(overlayLayout, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
}
I don't claim this to be THE solution...just the one that works for me.

I created two GameViews in the same layout, one for the scenery and one for the objects

Related

Drawing line or connection between Views in Canvas

I am trying to achieve something like in below image. I have several Buttons around a View and would like to connect them using Canvas on their background. I am able to place the Buttons and View in a manner required for my project, but I've no clue how to place a Canvas behind it and connect all of the Buttons to my View.
I've no clue how to place a Canvas for such requirement and how to find the Button's & View's center co-ordinates in Canvas so that I can draw line between View's Coordinate and Button's Coordinates.
For this, you will need a custom ViewGroup class (please refer to this doc).
You could also just start right away with Linear or RelativeLayout as a superclass, this way you will have all the chil-positioning logic ready for you.
You will need to override the dispatchDraw method. Inside dispatchDraw(), iterate through your children and draw your lines on the canvas. Please tale care to draw the children after you draw the lines.

How to create a custom Android view? Using XML objects or a drawing API?

I'm trying to create a new view that would:
load an image
allow the user to zoom and rotate the image with two fingers while a "cropping box" stays translucent over the top while the image extends beyond the "cropping box"
with the end goal of being able to mark the rotation and position of the main image (so that later i could crop out or show the area within the cropping box)
I'm wondering if I can do this with an ImageView holding the image in the background and another ImageView holding the crop box on top of it, then using TouchEvents to move the image, would this work?
Or do I need to use some drawing API on a 2D surface?
I'm just really new to creating custom objects in Android that aren't just customized out-of-the-box Views.
What's the standard way of creating something like this?
Thanks!
Create a Compound View by extending RelativeLayout with two overlapping ImageViews in it. Then override onTouch event or override onGestureDetector interface in that newly created View.
Official Documentation: http://developer.android.com/guide/topics/ui/custom-components.html
Another Tutorial: http://www.vogella.com/tutorials/AndroidCustomViews/article.html

How to draw Custom View Extending Relative Layout to a canvas

I have my main activity which creates an instance of SurfaceView. In the SurfaceView I am creating several simple objects from bitmaps. I pass a canvas element to them (objectX.draw(canvas)...etc) from a render method in the SurfaceView. all of this is working as i would like, however I would like to do the same with a custom RelativeLayout.
For example i would like to create a custom class extending RelativeLayout and fill it with various objects such as ImageView etc and then from the SurfaceView call a method which draws this to the canvas.
I have been looking for tutorials to help me understand how to do this but cannot find anything. I understand that I have to draw a bitmap of the RelativeLayout and then in turn draw that to my canvas which the surface view is passing in to it. I think a lot of my issues may be coming from the fact that i am not trying to ever add the Custom RelativeLayout to the screen, instead I would like to create it by inflating an xml layout and simply drawing to a passed in canvas.

Android: Displaying a 2-D animation on top of Existing View/Activity

I've been banging my head against the wall for a couple hours trying to figure out the best way to overlay an animation on top of a current View. I have a ListView, and I want to display an animation (say a frame-by-frame bomb explosion) on top of the ListView when a user clicks a button.
Can someone point me in the right direction?
This is what your looking for:
http://developer.android.com/reference/android/view/SurfaceView.html
From the link:
The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it. This can be used to place overlays such as buttons on top of the Surface, though note however that it can have an impact on performance since a full alpha-blended composite will be performed each time the Surface changes.
Or you could subclass the ListView and use the canvas to draw what ever 2d stuff you want:
http://developer.android.com/guide/topics/graphics/2d-graphics.html

GLSurfaceView/SurfaceView overlap

I asked a question about this earlier but received no responses, so I'm trying again.
I need to do a rendered 2D picture with some accompanying labels and graphics on a Motorola Xoom, Android 3.0. Although what I need can be done with just a SurfaceView (Canvas) or just a GLSurfaceView, I would really like to use both because the rendering is faster with the GLSurfaceView, and the labeling and graphics are easier with the SurfaceView. The visual layout is as shown below.
I tried to put the SurfaceView on top by declaring it in the layout XML after the GLSurfaceView. The SurfaceView is transparent (except for where I explicitly draw stuff) so that the GLSurfaceView can still be seen.
This approach has worked pretty well with one huge exception. Anything that I draw on the SurfaceView that is in the GLSurfaceView region does not show up at all. To verify this I drew some text that was right on the boundary (some in the shared region, some just in the SurfaceView region), and it was chopped off at the GLSurfaceView boundary. I have tried using the "bringToFront" method to fix this, but it hasn't worked.
Can anyone give me some ideas on why this isn't working or what I can do about it? Is it that the GLSurfaceView is in front, or is that the GLSurfaceView writes directly to the video memory, so it doesn't matter if something is in front of it?
The way SurfaceViews work will make it impossible to do what you want. You will have to render your text inside the GLSurfaceView.
Never try to overlap a GLSurfaceView with anything (above or below). At best it breaks on your device and you catch it early, at worst it works on one device and not others. Bite the bullet and do everything in a GL view or none of it. If you need the speed then GL is the way to go.
we should set setZOrderMediaOverlay and setZOrderOnTop to true value
setZOrderMediaOverlay
Added in API level 5
void setZOrderMediaOverlay (boolean isMediaOverlay)
Control whether the surface view's surface is placed on top of another regular surface view in the window (but still behind the window itself). This is typically used to place overlays on top of an underlying media surface view.
Note that this must be set before the surface view's containing window is attached to the window manager.
Calling this overrides any previous call to setZOrderOnTop(boolean).
setZOrderOnTop
Added in API level 5
void setZOrderOnTop (boolean onTop)
Control whether the surface view's surface is placed on top of its window. Normally it is placed behind the window, to allow it to (for the most part) appear to composite with the views in the hierarchy. By setting this, you cause it to be placed above the window. This means that none of the contents of the window this SurfaceView is in will be visible on top of its surface.
Note that this must be set before the surface view's containing window is attached to the window manager.
Calling this overrides any previous call to setZOrderMediaOverlay(boolean).
Please refer to this link :
http://developer.android.com/reference/android/view/SurfaceView.html#setZOrderMediaOverlay(boolean)

Categories