Layering Views on a SurfaceView - android

I am trying to build a simple game. I have a SurfaceView, on which I draw the background for the game:
Canvas canvas = surfaceHolder.lockCanvas();
//draw on canvas....
surfaceHolder.unlockCanvasAndPost(canvas);
I have a View that I want to 'layer' on top of the SurfaceView, but I still want to be able to see the background underneath it. How do I draw the view on top of the SurfaceView. The View has its own onDraw method, with an associated canvas, so I'm assuming that I need to place the View on top of the SurfaceView where I drew the background?

There may be a more efficient way to to do this, but when it comes to stacking views on top of one another, you could put the SurfaceView inside a FrameLayout, and then put the view you want on top after the SurfaceView in the XML, but still inside the FrameLayout (meaning it's drawn later, and thus on top). This will accomplish the stacking you desire.
If you wish to position the view that will go on top of the SurfaceView anywhere else than exactly matching it, or the top left, then you could use a RelativeLayout where you layout the SurfaceView with alightParentLeft, alightParentTop, alignParentBottom, and alightParentRight all set to true. Then again having the view you want drawn on top coming after the SurfaceView in xml will draw it on top, and you can position it wherever you want.
Now as for you wanting to the view on top of the SurfaceView to be see through, you can do that by setting it's alpha value. if you are aiming for 3.0+ you can just use a view's .setAlpha method, but if you are aiming for lower, you could set a zero millisecond AlphaAnimation to set the alpha of the view (There may be a better way to do this, but this is the only way I to set alpha on views pre honeycomb).
Hope this helps! Best of luck!

Related

How to draw outside view bounds?

How can I draw (bitmap, line, etc) outside the bounds of a view? From the view's onDraw(), I've read this is not possible as everything drawn will get clipped to the view's bounds.
I did come up with one solution but I'm hoping there's a better one. What does work is to create a transparent view that is at the top of the z order and includes the area I want to draw in (the entire app client area). Then, whenever I want to draw outside some child view, I can simply translate to the coordinates to the transparent view and draw there.
I also read about SurfaceView hoping that would do what I want. But I think it's main purpose is to provide drawing in a separate thread and doesn't solve the problem I'm discussing.
To be clear, it isn't sufficient to simply draw in the parent of the target view because other views in the parent will be higher in the z order and hide the drawing.
Intuition tells me there's a "right way" to do this. Anyone know?
I'm drawing the conclusion that the right way is to do what I proposed - create a transparent view that is at the top of the z-order for the space you need to draw in.
I come to this conclusion after learning how the Navigation Drawer drawing works - exactly in this way. So, if Google uses this technique, I conclude that it's the best way available.

drawing outside a view's canvas, can it be OK?

I have a custom view that extends ImageView and displays an image and a text header. The text is drawn via drawRect and drawText overriding onDraw.
The first image is the typical use case: The header is inside the canvas bounds.
I'd like to be able to draw the header outside the canvas bounds. If I just draw it outside the bounds, just like image 2, the result is correct, ie. the rectangle is drawn outside the canvas and the text too.
However, I wonder if this works by accident and what kind of problems I may expect. I suppose it's a bad thing to draw outside the canvas bounds, but it'd be very convenient for me because I won't need to further complicate this custom view, or wrap it inside a container, or create another view, etc... I've only tested it on a couple devices I own and it works...
Can anybody share some thoughts on why this is OK, it doesn't really matter, or is very wrong?
For those interested, I've found a legit way to do this:
set the bottom padding to the header size plus the blank space
draw normally, now everything's inside the canvas and the imageView is adjusted to the requested padding, leaving the bottom padding area free to draw my header :P

Make surface view transparent to current layout only

In my app i am using surface view for drawing perspective and some buttons on the same layout.
I am done with the drawing part but don't know how to make surface view transparent for the current layout only.
When i use holder.setFormat(PixelFormat.TRANSLUCENT); it shows my previous screen.
I have also tried the setZOrderOnTop(true); method but it makes my other buttons hidden/covered when drawing.
And using setZOrderMediaOverlay(true); put the view beyond current layout, if i am moving my finger over the screen it is drawing there as i can see the saved file, but not showing on screen.
I want to make it transparent for current screen without setting the z order.
Forks, help me to make this happen.
Thanks in advance.

Drawing on screen, do I need surface view?

I am always confused about this and I need a pointer on how you would do it. If create a an xml layout with multiple imagesview and text view. And Lets say I want to draw line between two images and move an image along this line. How do I draw this line? I know I can get location of both images view so I have x1,y1 and x2,y2. My problem is with drawing.
Do I need surface view to have the drawing capabilities and loading bitmaps on the screen along the line?
If yes, then I guess I should always surface view to fill the screen and views on top just incase I need to draw which seems kinda wrong?
IF no (I hope thats the answer), then how do I draw lines, or load bitmaps on screen using only X,Y values?
I hope I was able to explain my confusion
Thanks
EDIT: Actually I thougth of a way of explaining my confusion better.
When you create an activity with xml layout you have something like
onCreate (){
setContentView(R.id.layout)
}
but when you have activity with drawing view you have something like
onCreate (){
SurfaceView v = new Surfaceview(this);
setContentView(v)
}
My problem is that we have to set the content layout to EITHER xml layout or to be drawing area . What if I want to set it to my xml layout and at the same time I can draw anywhere on the screen (over images view, empty areas, TextViews ..etc)
See my question?
That depends on what your desired result is and how much flexibility you need. You can have a look at this android Animations tutorial (the site is down at the time of posting but google has it cached).
If you don't need flexibility, then for your line, you might be able to create a View in your xml with an android:background fill color and a size that makes it look as you wish. You could then use an Animation on your bitmap's ImageView to translate it along the line, and use a listener on said Animation to show/hide the various Views as necessary at the beginning or end of your Animation.
If you need flexibility, the SurfaceView is probably your best bet.

Android: SurfaceView and Z-Level Question

I have a FrameLayout containing first a SurfaceView, and second a RelativeLayout which in turn contians various Buttons and TextViews.
Upon the canvas of the SurfaceView I am drawing numerous Bitmaps, and, via Touch and Motion Events am allowing the user to drag them around.
These Bitmaps, when dragged around pass underneath the Buttons etc that are inside the RelativeLayout.
Now, it's my (possibly mistaken) understanding that the "Z-level" of the SurfaceView, or whatever it has that passes for it, is entirely unrelated to the actual Z-level of the rest of the Layout. Is this the case? If so, how may I get around it, so that dragged Bitmaps are drawn ontop of other Views? Or what other way can I implement a full-screen canvas and yet not have my buttons etc act like the controls of an overlay.
I guess what I actually need is an underlay, where touch events can still be picked up by the Buttons etc underneath. But I don't know how to achieve this, as, when redrawing my Canvas, I have to also redraw the background.
Can I swap the order of the RelativeLayout and the SurfaceView inside the FrameLayout, and then make the background of the Canvas transparent? If so how? Will touch events still "fall through" to the buttons underneath?
Thanks for bearing with me, I know I'm a bit of a waffler.
SurfaceView doesn't work that way.
SurfaceView has two parts, the "view" part and the "surface" part. The "view" part is a transparent hole that is laid out with the other view elements, and composited onto the view layer. The "surface" part is a completely separate layer that will be positioned and scaled to match the "view" part, and composited by the system compositor rather than the app.
You can control the Z-order of the "surface" layer when the SurfaceView is first created, but it's going to be above or below all View elements. It can't go above some Views and below others because they're completely independent layers. The "surface" layer does not catch input events, so having it on top (via SurfaceView#setZOrderOnTop()) doesn't affect input focus.
For API 14+, you can use a TextureView, which behaves in a more View-friendly way.
Edit: for full details, see the much longer explanation.
Can you clarify a little bit more? In your SurfaceView do you have a background assigned? If not, you could probably also use AbsoluteView if your intention is to simply drag pieces around. If there is no background, you should be able to place the entire view above the RelativeView that you have and only have the various Buttons and such drawn on the view on top, which would be draggable and remain above everything else.

Categories

Resources