I want to create a hierarchy of Views in layers one on top of the other that is, roughly:
FrameLayout {
SurfaceView
View
View
SurfaceView
View
SurfaceView
}
I want each SurfaceView's draw events to appear in the correct position in the hierarchy. For example, the top surface should appear in front of everything. The bottom one should appear behind everything.
Unfortunately, I can make each surface appear in front of everything using setZOrderOnTop(true) and I can make each surface appear at the bottom by NOT doing this, but I can't make one appear in the middle. How would one do this?
FrameLayout is designed to block out an area on the screen to display a single item. Generally, FrameLayout should be used to hold a single child view, because it can be difficult to organize child views in a way that's scalable to different screen sizes without the children overlapping each other.
I suggest you use a LinearLayout or RelativeLayout instead.
At the time of writing, this appears to be impossible.
Related
I'm trying to build a point-and-click adventure for Android without using any pre-written engine, but I'm stuck in a really crucial point!
I have a HorizontalScrollView bigger than the screen, so the user can scroll left and right in portrait mode to search around rooms, now what I need is to insert items that the player can use inside this View.
I'm trying to use static ImageView, but I'm really confused on how to insert Views in an absolute position inside the HorizontalScrollView. All I know is that Android manages Views location relative to other views (align on top, next to, bottom of), but what I use if I need to position a View in a specified position using specific coordinates without worrying that the image will be misplaced in a different screen size for other Android devices?
I really am confused on how position views in Android :/
Consider creating your own view instead of abusing HSV.
Custom views, doDraw() method, canvas and even gesture detection is not that hard.
Here is a link that will help you with basics, simple viewport implementation for android with scrolling via key events: http://sonnygill.net/android/android-viewport/
what I use if I need to position a View in a specified position using specific coordinates without worrying that the image will be misplaced in a different screen size for other Android devices
Actually, that's exactly the reason ViewGroup (layouts) were created.
You should choose the right layout based on your requirements.
If you do want to position the views by yourself, you can create your own custom ViewGroup by extending one of the view group classes and override the onLayout(...) and onMeasure(...) methods which are used to position and measure child views (in you case, probably the ImageViews) respectively.
You can use this example of FlowLayout as a reference on how you can write your own custom ViewGroup.
Please note that if your content is bigger than the screen as you mentioned, the HorizontalScrollView should be a parent of a single child (which should be the ViewGroup containing your images).
I would like to make a simple Android game where a large background image is displayed and some other images are displayed in specific locations over it, where the other images may be clickable.
Here's a quick sample image of what I'm talking about:
The user should be able to tap the soccer player or the moose (ah, the classic "soccer player moose problem"!)
How should I render this screen (which layouts and views?) so the user can interact with it and it will scale properly on different devices?
I would use a RelativeLayout.
You can set the you background image to the layout (fill_parent for height and width).
You can then put your ImageViews, containing your moose and soccer player down on the layout relative to the top or sides of the sceen, or relative to each other (making sure to specify "dp" units for everything). Set the backgrounds of your ImageViews to be transparent, and there won't be a bounding box problem (and/or you can also set your ImageViews alignment to be relative to each other, ensuring they don't overlap).
I think this is the simplest way to do this - it is then super easy to attach onClickListener to your ImageViews in your Activity, and you are done.
This type of layout will work the same on all devices and screen sizes.
There are some small gotcha's with RelativeLayouts, but they are pretty simple once you get into them, and provide fast rendering (since the view hierarchy is usually shallow). Good Luck.
ImageView for the clickable elements seems like a fine choice to me. For the background I would just set your image as the background of the parent layout i.e. RelativeLayout
SurfaceView for the whole thing (with your field as a background) and regular *ImageView*s for added elements. You can easily recover the click coordinates from the SurfaceView and thus know what element has been touched.
SurfaceView might offer you additional possibilities anyway.
For most images, I'd use an ImageView for each one, like FoamyGuy said.
If they're close enough for overlapping bounding boxes to be an issue, you can still use an ImageView for each, but with a variation of this answer, testing alpha for each ImageView in range.
I would agree with both FoamyGuy and Booger that if your only goal is to place static images onto the screen that do something when you click them, RelativeLayout and ImageViews all the way.
But...
If you are looking to randomly spawn multiple images onto the screen in intervals and have them move around for the player to interact with while explosions are going off and maidens are being kidnapped, you should look into SurfaceView, Canvas, Drawable, TouchEvents, and FrameBuffers.
I have a 'Portrait mode' tabbed based application that contains a SurfaceView (with a camera preview on it) within one of the tabs. I have been creating my camera code from the Android API Demos and I have it all set-up working correctly bar one thing. The resulting camera preview is stretched and scaled making the preview look off.
Ideally I want to render the SurfaceView at the native preview size defined by the camera within the tab. However that would involve making the contents of the tab larger than its parent! (Or rather larger than the FrameLayout the tab activities are contained in).
How can I go about Achieving this?
Image of problem:
Make the FrameLayout the root object, then pile the camera view in it, then header and the tab widget. You may have to do some fancy work with gravity settings and stacking the header/footer in linear layouts but it definitely is possible.
aka:
frame.addView(cameraPreview);
frame.addView(header);
frame.addView(footer);
This will draw the objects in layers.
EDIT: If you don't want to use your current frame layout, just make another one. Stack the header, frame layout, and footer inside a linear layout. Create a new frame layout, add the linear layout to it, then add the preview onto it to draw over it.
I'm working on the controls for a game, and require part of the control panel (gray in the figure below) to change dynamically, either showing a single canvas (left) or 5 buttons (right). The border between the lower-row views should always be positioned at exactly the same x-position as the border between the buttons on the upper row, as shown. At the same time, all twelve upper buttons should be scaled and distributed evenly.
I've considered several approaches, but as of yet none do all of what I want:
Using two LinearLayouts, one for each row of controls: reliably aligning the borders seems to be impossible, and replacing part of the layout is difficult at best.
Using a TableLayout: again, replacing a portion of the layout is difficult.
Using a RelativeLayout: resizing and aligning buttons independently of the screen size doesn't seem possible
Any suggestions for an alternative method, or on how to make one of the above approaches work? It would also be nice if there were some way to animate the change of views, i.e. sliding in the buttons from the left over the canvas. Thanks!
Interesting, I've done this several weeks ago. What I did is to make use of this property of View object: "Visibility". So that means at a fixed position, I can set any View to display on to, not depending on any type of Layout, it can be Visibility.GONE, Visibility.VISIBLE or Visibility.INVISIBLE.
In my app, I used RelativeLayout to set relative position to the right side TextView.
Give it a try :)
In order to close this question: I have solved the problem by writing a custom layout class that places and sizes the child views without heeding the measured size of the children. Effectively this gives me the behavior of a linear layout with layout weights, but is more deterministic with border placement.
A ViewAnimator is used to switch between the Canvas and the Buttons.
I'm trying to layer graphics one top of each other, like an icon over a background, with the second layer (icon) at a certain pixel offset from the top left corner of first layer (background). Since each layer will eventually have its own animation, I'm placing each in its own View.
For my implementation I have two ImageViews, one for each layer, inside a RelativeLayout, which in turn is inside a ScrollView. ImageViews are positioned using layout_margin relative to the top left corner (0,0). The first ImageView is larger than the screen (background), while the second ImageView is smaller than it (icon). ScrollView automatically resizes the first ImageView (background) since it is larger than the screen, it does not resize the second since it is smaller (icon).
I need both of them to scale together, and I also need the positioning of the second layer over the first layer to adjust itself accordingly. This actually works well in a layer-list, but due to the animations I am forced to use Views. How can I scale and position multiple Views together, or do I need to build my own class for something that seems like it should be fairly basic?
Thanks in advance.
I had a similar problem in my android application. Android has introduced new set of API's to help us on this, setScaleX() and setScaleY().
Just call layout.getParent().setScaleX(); and layout.getParent().setScaleY();