本文共 11157 字,大约阅读时间需要 37 分钟。
In the previous installment of Android Layout Tricks, I showed you in XML layout to reuse and share your layout code. I also mentioned the <merge />
and it’s now time to learn how to use it.
The <merge />
was created for the purpose of optimizing Android layouts by reducing the number of levels in view trees. It’s easier to understand the problem this tag solves by looking at an example. The following XML layout declares a layout that shows an image with its title on top of it. The structure is fairly simple; a is used to stack a on top of an :
This layout renders nicely as we expected and nothing seems wrong with this layout:
Things get more interesting when you inspect the result with . If you look closely at the resulting tree you will notice that the FrameLayout
defined in our XML file (highlighted in blue below) is the sole child of another FrameLayout
:
Since our FrameLayout
has the same dimension as its parent, by the virtue of using the fill_parent
constraints, and does not define any background, extra padding or a gravity, it is totally useless. We only made the UI more complex for no good reason. But how could we get rid of this FrameLayout
? After all, XML documents require a root tag and tags in XML layouts always represent view instances.
That’s where the <merge />
tag comes in handy. When the encounters this tag, it skips it and adds the <merge />
children to the <merge />
parent. Confused? Let’s rewrite our previous XML layout by replacing the FrameLayout
with <merge />
:
With this new version, both the TextView
and the ImageView
will be added directly to the top-level FrameLayout
. The result will be visually the same but the view hierarchy is simpler:
Obviously, using <merge />
works in this case because the parent of an activity’s content view is always aFrameLayout
. You could not apply this trick if your layout was using a LinearLayout
as its root tag for instance. The <merge />
can be useful in other situations though. For instance, it works perfectly when combined with the<include />
tag. You can also use <merge />
when you create a custom composite view. Let’s see how we can use this tag to create a new view called OkCancelBar
which simply shows two buttons with customizable labels. You can also . Here is the XML used to display this custom view on top of an image:
This new layout produces the following result on a device:
The source code of OkCancelBar
is very simple because the two buttons are defined in an external XML file, loaded using a LayoutInflate
. As you can see in the following snippet, the XML layout R.layout.okcancelbar
is inflated with the OkCancelBar
as the parent:
public class OkCancelBar extends LinearLayout { public OkCancelBar(Context context, AttributeSet attrs) { super(context, attrs); setOrientation(HORIZONTAL); setGravity(Gravity.CENTER); setWeightSum(1.0f); LayoutInflater.from(context).inflate(R.layout.okcancelbar, this, true); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OkCancelBar, 0, 0); String text = array.getString(R.styleable.OkCancelBar_okLabel); if (text == null) text = "Ok"; ((Button) findViewById(R.id.okcancelbar_ok)).setText(text); text = array.getString(R.styleable.OkCancelBar_cancelLabel); if (text == null) text = "Cancel"; ((Button) findViewById(R.id.okcancelbar_cancel)).setText(text); array.recycle(); }}
The two buttons are defined in the following XML layout. As you can see, we use the <merge />
tag to add the two buttons directly to the OkCancelBar
. Each button is included from the same external XML layout file to make them easier to maintain; we simply override their id:
We have created a flexible and easy to maintain custom view that generates an efficient view hierarchy:
The <merge />
tag is extremely useful and can do wonders in your code. However, it suffers from a couple of limitation:
<merge />
can only be used as the root tag of an XML layout<merge />
, you must specify a parent ViewGroup
and you must setattachToRoot
to true
(see the documentation of the method) In the next installment of Android Layout Tricks you will learn about ViewStub
, a powerful variation of <include />
that can help you further optimize your layouts without sacrificing features.
.
转载地址:http://oalli.baihongyu.com/
[...] Romain Guy: Android Layout Tricks #3: Optimize, Part 1 var disqus_title = “This Weeks Off-Site tutorials – W/C 2nd March 2009″;var disqus_message = ” Romain Guy: Android Layout Tricks #3: Optimize, Part 1 “;var disqus_developer = 0;View the forum thread. Add new comment [...]
Hi Thanks for the tips….
I have some query regarding hierarchy viewer..Can you help me on this?I connected my G1 phone and launched the hierarchy viewer. I then selected the device and clicked “Load View Hierarchy” option,the layout didnt get loaded but I got a “java.net.SocketException :Connection Reset”.
Then i found that the view server was not running,while the device is connected. But it was running with the emulator HierarchyViewer worked fine with the emulator,but not with device.Alternately I tried the adb shell command “service” to start the view server on the device which too didnt work…
HierarchyViewer cannot work with production G1s. You need an engineering or custom build to make it work. This is for security reasons (otherwise HierarchyViewer would let you inspect all the UI data, including passwords, of any app of any phone.)
Thanks for the help…
really nice tutorial !
[...] A ViewStub is a great compromise between ease of programming and efficiency. Instead of inflating views manually and adding them at runtime to your view hierarchy, simply use a ViewStub. It’s cheap and easy. The only drawback of ViewStub is that it currently does not support the tag. [...]
[...] A ViewStub is a great compromise between ease of programming and efficiency. Instead of inflating views manually and adding them at runtime to your view hierarchy, simply use a ViewStub. It’s cheap and easy. The only drawback of ViewStub is that it currently does not support the <merge /> tag. [...]
[...] A ViewStub is a great compromise between ease of programming and efficiency. Instead of inflating views manually and adding them at runtime to your view hierarchy, simply use a ViewStub. It’s cheap and easy. The only drawback of ViewStub is that it currently does not support the <merge /> tag. [...]
Hey, nice tips. I’ll buy a glass of beer to that person from that chat who told me to visit your site :)
[...] A ViewStub is a great compromise between ease of programming and efficiency. Instead of inflating views manually and adding them at runtime to your view hierarchy, simply use a ViewStub. It’s cheap and easy. The only drawback of ViewStub is that it currently does not support the <merge /> tag. [...]
I’m confused [android newb alert]. The second xml snippet is not in MergeLayout.zip. Is that supposed to be okcancelbar.xml? (It would really help if you put the file names on the code snippets so we know what we are looking at.) If so then I get the error:
No resource found that matches the given name (at ‘layout’ with value ‘@layout/okcancelbar_button’).
for both of those resources. R.layout defines main, okcancelbar and okcancelbar_button. Dont those all have to exist as xml files in res/layout? There is only a main.xml. Is something missing?
Hi the code given by you is not working properly .
it throws errors.Would be a nice tutorial if it was complete! As Xylenz noted, two .xml files are missing: okcancelbar and okcancelbar_button. Also, the zip includes R.java, but this file should be auto-generated, not included in the project manually.
While these are simple items to address by an experienced Android developer, they’re serious errors for a tutorial intended to be useful to people that don’t know much about Android development. I’m assuming such a basic tutorial is not intended for the experienced Android developer.
i tried to run your code on eclipse, but got these build errors:
Description Resource Path Location Type
error: No resource identifier found for attribute ‘cancelLabel’ in package ‘com.example.android.merge’ main.xml /MegeActivity/res/layout line 14 Android AAPT Problem error: No resource identifier found for attribute ‘cancelLabel’ in package ‘com.example.android.merge’ main.xml /MegeActivity/res/layout line 14 Android AAPT Problem error: No resource identifier found for attribute ‘okLabel’ in package ‘com.example.android.merge’ main.xml /MegeActivity/res/layout line 14 Android AAPT Problemcan someone help me?
Hi,
I am new to android development and I have downloaded the above example’s zip file to try out. However, as others have already mentioned, the zip file is missing a couple of files.
Could somebody please post these missing files so that the example can be tried out by Android noobs such as me?
Thank you in advance for your troubles.
Regards,
PM.[...] Android layout tricks it’s another article where you can find the necessary details that can help you to work with FrameLayout. [...]
Dude, u are awesome . Thanks for the simple concept. I was looking for this tiny detail all over and it was just so annoying.
Thanks you so much.Keep up the good work !!!
I’m having the same problem as some of the users above. Some files are missing from the sample. Any plans to remedy this? I am new to Android, and the fix is not immediately clear.
Thanks
Totally agree with comments on the xml. There appear to be cross-references between two xml files which are un-named. I’ve tried a number of permutations without success. Also the deprecated references to R.stylable. Help us out Romain – please.
This was a good post.. This was my 1st time to this blog. Appreciate you for sharing . I have to subscribe to this website. I was a boat repairman for five years. Our do-it-yourself tip of the day is this: Please do not make an attempt a hard repair job without a professional. That will cost you additional money in the end. Thank you once again…..
There are definitely plenty of particulars like that to take into consideration. That could be a nice point to deliver up. I offer the ideas above as basic inspiration however clearly there are questions like the one you deliver up the place a very powerful factor will probably be working in trustworthy good faith. I don?t know if finest practices have emerged around things like that, but I am certain that your job is clearly identified as a good game. Both boys and girls feel the affect of only a moment抯 pleasure, for the remainder of their lives.