I am creating a 2d puzzle game on android and want to get the community's input on a design decision. The basic design is this. There is a SurfaceView one which the 2d graphics are drawn in a background thread. Then I also have a RelativeLayout that overlays the surface view. The layout .xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/root"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" >
<SurfaceView
android:id="#+id/game_surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<RelativeLayout
android:id="#+id/game_overlay"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
All touch events will be received by the game_overlay and will be routed to the game thread as needed. I will use LayoutInflater to inflate a layouts and place them inside game_overlay, then clear the game_overlay when needed. My rational for doing things way is that you get the best of both worlds. You don't have draw your own custom buttons to the canvas (Like a reset level button), rather leverage all that powerful android layout functionality. However you are able to perform the game rendering in the background, and have that thread stay alive all the time.
So now onto my questions. If you have tried something like this before I would like to hear your experience. Can I expect to pay a performance penalty for layering views like this? And more importantly would that performance hit be detrimental to the app's frame rate? Is there any other problem with this approach that you can spot.
For better game performance you should keep buttons at minimum since its for smart devices , try to rely on touch inputs for game play.
For custom buttons i disagree ,Also having your own buttons is better for visulation. It makes fancy your game.
And for your question yes you should avoid unnecessary capsulation. But i don't think it will cause a giant performance problem.
This can be a nice tutorial for surface click me
Related
Is it possible to hide this in XML file:
myactivity.xml has more than 80 views, bad for performance ?
I have a complicated UI. So, I want to hide this warning. I mean no way to switch UI into ListView, etc.
I think the issue here is the layering. If it has to layer 80 views on top of one another, that is really bad. Otherwise, that is a LOT to manage
You can see just how bad your UI performance is by using the Android tools in Developer Options > Debug GPU overdraw (on) and Show Surface updates to On. That will show you the performance issues.
Now to fix them, custom view XML'scontaining your subviews are the way to go.
Code maintainability is really important here. Right now a single one line change can screw up everything whereas with custom loaded subviews you minimize this greatly and ask a bit less of the OS at the onset potentially.
You can hide/ignore it by adding tools:ignore="TooManyViews" to the view that is making that error. For example:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
...
</LinearLayout>
will be
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="TooManyViews">
...
</LinearLayout>
Note that this just hides the Lint warning and doesn't do anything else.
I'm no Android expert but I am aware of discussions regarding the appropriate use of LinearLayout and RelativeLayout, keeping the view hierarchy as small as possible, avoid unnecessary passes of onMeasure(), etc.
Lets imagine I have two ImageView's that I want to position completely INDEPENDENTLY, the first in the center of the parent and the second in the bottom left of the parent. (note this is a vastly simplified example of far more complex real life requirements).
The obvious way to solve this is using a RelativeLayout...
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="#drawable/first_image" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="true"
android:layout_alignBottom="true"
android:src="#drawable/second_image" />
</RelativeLayout>
However something keeps telling me that a RelativeLayout isn't appropriate in this situation because I don't want to organise the children relative to each other. All I want to do is position the children according to the parent and I wonder if using a RelativeLayout causes some unnecessary layout calculations that I don't really require.
I am wondering if there is another ViewGroup type that would perform better? Its totally possible to achieve what I want with a FrameLayout for example but I've no idea if this is more performant or if I am abusing the intent of a FrameLayout etc...
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/first_image" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:src="#drawable/second_image" />
</FrameLayout>
Maybe there is another Layout type I am unaware of?
Short answer
Given the information you have provided, the FrameLayout has a good chance of performing better. As you may have learned already watching (Adam Powell quote in Google I/O 2013 conference),
[...] RelativeLayouts will measure child views more than once in order to solve some of the constraints you give it. So, being generic has a cost [...]
From what I read and understood, this is not guaranteed and it depends on the constraints you give it.
Long answer
It really depends.
We all read Romain Guy blog post : Android Layout Tricks #1, who said that most people misinterpret his post and started using RelativeLayout everywhere.
This post, if you haven't read it, talks about how removing one hierarchy level using a RelativeLayout instead of a LinearLayout which saves loading time in a list.
Basically, it means that if you don't need them, as you described it yourself
[...] I have two ImageViews that I want to position completely INDEPENDENTLY [...] I don't want to organize the children relative to each other
you should not use them because of that reason.
Concrete example of : "Don't use them if you don't need to."
For instance, in one of our applications, we have serious performance issues on devices running Gingerbread -- which we want to support.
Our most complex layout involves a vertical ScrollView, attached to the current activity, in which we have several containers and one HorizontalScrollView that displays images and information which are contained in a complex LinearLayout.
We started to replace the LinearLayout by RelativeLayout. The result: no obvious improvement -- equivalent or maybe worse.
Since that layout is fairly complex, adding more RelativeLayouts embedded in each other just increased the onMeasure() calls that were made for a single draw.
Even a small circular ProgressBar was now spamming the UI thread with several measure calls because it was in one of those embedded RelativeLayout which triggered recalculations of the whole view.
I'm trying to make the background of my app have randomly floating bubbles. I've been looking around for anything similar, such as falling snowflakes, rain, etc. but I can't seem to find any examples.
Even if I can't make a bubble.png float randomly upwards, I'd like to at least have a . character or something that could represent "bubbles" like in a soda.
Any ideas or references? Thanks!
You could place a SurfaceView behind your primary UI in a FrameLayout and draw the bubbles in the SurfaceView following one of the available tutorials. The rest of your UI would then overlay on top.
Example:
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/surface" />
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/app_content">
<!-- Normal app UI goes here -->
</FrameLayout>
</FrameLayout>
Warning: No matter what approach you take you're going to be redrawing the entire screen quite frequently several times per frame. (Animating the background plus drawing the UI.) Some ways will be faster than others but you are choosing to do more work than most apps do in drawing their UI. You will need to be mindful of performance and small inefficiencies; they will add up quickly.
I have a background in iPhone development, which may be a cause of some of my confusion with Android, which I am very new at developing.
My question is this: How to I create two TextViews, and specify their exact location on screen? For example, on the iPhone, I would create a UILabel, generate a rectangular frame that specified the label's size and position, and then set this rectangle to the frame property of the UILabel.
If you can help me understand the similarities with Objective C and iOS' UILabel, that would be most helpful.
On Android, we don't use absolute screen positions. This is highly discouraged. It's pretty understandable that you think this way if you are coming from iOS. But you need to revise your habits.
Instead of absolute positions, we use layouts, such as LinearLayout, RelativeLayout or FrameLayout. All of these allow you to arrange your views dynamically. And in many cases, it will automagically adapt to the screen size, which vary a lot from device to device.
Actually, there's nothing exotic about dynamic layouts. Many major UI toolkits, such as GTK, or Qt, work similarly. Pixel position are a bad idea in my opinion, except maybe in the Apple world, where the OS and the hardware are tightly coupled, but this is an exception actually.
So, in your case, all that you need is to put your text views into the appropriate layout. Please read the documentation and tutorials about the different types of layouts mentioned above to decide which one is best. The question is how you want your views to be placed relatively to each other.
Create a basic Android project in eclipse. You will be having a main.xml layout file in your project. You can open it in Eclipse using Ctrl+Shift+r and keying in main.xml
copy paste this in your xml after clearing its content.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:text="TextView One"
android:layout_height="fill_parent"
android:layout_weight="1"></TextView>
<TextView
android:id="#+id/textView2"
android:layout_width="fill_parent"
android:text="TextView Two"
android:layout_height="fill_parent"
android:layout_weight="1"></TextView>
</LinearLayout>
I have a widget layout xml which sets the src to the delivered android widget 4x1 frame image.Here is the widget layout code.
<?xml version="1.0" encoding="utf-8" ?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tuwidget" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:id="#+id/tuwidget_img_btn"
android:src="#drawable/widgetinitial"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</AbsoluteLayout>
#drawable/widgetinitial holds the widgetinitial.png image example 4x1 at developer.android.com (AppWidget design guidelines).(4x1_Widget_Frame_Portrait.psd) What I am trying to do is display an image inside the delivered frame instead what happens is the frame image goes away and only the image I am trying to display shows up. How can I display the image inside the bounding box or the background?
Any help is much appreciated.
Another question - I think I saw in a couple of forums AbsoluteLayout is a deprecated feature for Android 2.1 and above. Is that correct? and does using AbsoluteLayout throws any force close or other exceptions?
AbsoluteLayout is deprecated. It doesn't throw any exceptions, but its generally a bad idea to use it because it is really hard to design a layout that will work on all screen sizes. There is generally a better way to do it using a different layout.
In your case, I don't follow exactly, but it sounds like you want to layer two widgets on top of each other? An image with a frame? To do so, I'd use a FrameLayout. This is designed for having multiple layers of images.
Common layout objects is also a good guide to the basic layout types.
Take a look at the end of the page 2 of this pdf