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)
Related
Can not make a bitmap from a complicated view with state machine.
I have a RelativeLayout in which a dynamic tree of views handles touchevents to draw graphics. It uses a state machine to keep track of events like down, move and up and perform various drawing activities.
Now I want to make a copy (bitmap) of this RelativeLayout every time the view changes and display on the second screen. I have tried both methods I found online:
draw(theSecondCanvas);
Bitmap cache = getDrawingCache();
Both work most of time except occasional failure. The problem is both methods will eventually call every child views' draw() one more time to draw on the second canvas. But the state machine has changed to the different state based on the last touch event. It gives different drawing result or sometime error with null object reference because the additional drawing request has no touch event associated with it.
One option is for me to fix the complicated logic of state machine in the tree of views so it can handle an additional stateless drawing on the second canvas.
But I would think it has to be a simpler way to capture a bitmap from a view without drawing everything again. The view has done all the drawing inside already. It doesn't make sense to repeat the same work on the second canvas just to get a copy of bitmap.
Any suggestions? Thanks in advance!
I realized that off-screen rendering is not necessary in my case. I can intercept default canvas and draw on my own canvas with a bitmap. Then copy the bitmap to the default canvas. This solves the problem.
I'm making an android app which has Libgdx Stage handling the HUD. But how can I scale things I add to Stage?
I've tried some manipulations with Camera, Viewport, and none of the work properly. Let's say I want my ImageButton placed in the right top corner of the screen. I managed to do that manipulating with table positioning, it seems to be fine. But the problem appear when I run my app on my phone. The ImageButton positioned right but it's kinda small :-)
Thing is I want ImageButton look like on (540,800) resolution screen.
ImageButton is (65,65).
When it comes to bigger screensizes ImageButton starts to look small because it does not scale(or the viewport and camera stuff dont work well, I dont think the actual scaling is truly necessary)
I suggest you to check the documentation about Viewports, which is pretty clear, although a bit dated : https://github.com/libgdx/libgdx/wiki/Viewports
If you don't need to mess with the camera, don't bother to declare one. Simply use a stage, with includes automatically an orthographic camera. If you declare an Actor within the bounds of the viewport, it should scale properly depending on the type of viewport you selected. For instance :
FillViewport vp = new FillViewport(800, 1280); // fills the screen, adapting itself to actual screen ratio
Stage stage = new Stage(vp);
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
This is the scenario:
I have one image background set on an activity. On this background, a rectangle has been drawn (in other words, one image depicting a rectangle). I need to display text WITHIN this rectangle.
Right now, I have one solution in mind: since I'm going to optimize the UI for most screens (incl. tablets), I'm going to customize the main .xml layout for each screen size (multiple .xml layouts). Thus, I can manually set the place where the text area goes within the rectangle (+ its size).
I am most certain that this solution is NOT good. I'd like to hear some suggestions from more advanced developers. What would an elegant way of placing text over a background image showing a rectangle, so that the text stays within the rectangle's borders be?
Because I need to set particular positions for other UI elements (centered buttons (vertically/horizontally), I am currently using a Relative Layout.
By default if you have used dp as dimensional measure, your app should in theory work fine for all resoultions. Android by default scales the screen to fit different screens. AndroidDeveloper You just have to make sure that you have different images for resources (Rectangle image). There is another post in SO which you might be intrested to look into link
Cheers
RIchie
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