Layout weight / Layouts / LinearLayout

Layout Weights – Part 1

There is an often overlooked feature of layouts which is extremely powerful and allows us to get some pretty fine-grained control of the humble LinearLayout: Layout weights. We have briefly touched on layout weights in the Intelligent Layouts article, but we’ll cover them in a little more depth here.

Let’s start with a really simple example. Suppose that we want to split the display in half vertically with the following layout:

It shouldn’t be much of a surprise when we run this to see that the first of the child layouts (with the red background) fills the display because its layout_height is set to match_parent:

First layout fills the display
First layout fills the display

We could change the layout_height to be wrap_content, but this wouldn’t do what we want either because the layouts would both collapse to 0 height because they have no children. We can achieve what we want by applying a layout_weight to both of our child layouts:

If we now run this it does what we want:

Split display
Split display

So, what’s going on here? We’re defining each of the child layouts with a layout_width of match_parent, but by setting a layout_weight (i.e. changing the value of this attribute from its default of 0) we can tell the parent layout to divide the available space between controls. In this example, we have set the two layout_weight values of the child layouts to the same value, and they will be given an equal part of the available space.

If we are dividing the parent in to equal parts, we just set the children’s layout_weights all to 1. But if we want to divide it unequally, we can do that in a number of ways. We can either use decimal fractional values which total 1, or we can use integer values:

or

Both of these will produce the same result:

Biased split
Biased split

Hang on a second. While we’re certainly seeing a two thirds split, we actually gave the red layout a higher weight than the green, so we’d expect the red to take up two thirds of the available space. Moreover, when playing with layout weights it is sometimes possible to get things working both how we would expect, and how we’ve seen here. This is a common gotcha with layout weights, and the key here is that we have instructed both of the child layouts to try and fill the parent because of the layout_height=”match_parent”, and this causes the behaviour to be the opposite of what we expect. We can reverse this behaviour by changing the child layouts to use layout_height=”wrap_content” instead:

And this now does what we would expect:

Biased split
Biased split

In the concluding part of this article we’ll look at some more tricks that we can do with layout weights, and a further gotcha.

In a break with the tradition of this site, I have not included a link to the final code. The reason for this is that all of the example code fragments in this article is are pretty standalone and we are not iterating over the code to a final target. The individual examples can easily be cut and pasted individually, if required.

A Portuguese translation of this article by Lucio Maciel can be found here.

© 2011, Mark Allison. All rights reserved.

CC BY-NC-SA 4.0 Layout Weights – Part 1 by Styling Android is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Permissions beyond the scope of this license may be available at http://blog.stylingandroid.com/license-information.

13 Comments

  1. Thanks for the post. In the snippet
    “key here is that we have instructed both of the child layouts to try and fill the parent because of the layout_height=”match_parent”, and this causes the behaviour”
    I don’t understand the logic. This is a issue or I loose something?

    1. @Alceu to be honest, I don’t follow the logic either. But what is clear to me is that if you set all children to “wrap_content” there should be a different behaviour to setting all children to “match_parent”. I can sort of see that this is doing things in the opposite direction, so implies an opposite behaviour.

      Another way to consider things is: If I were writing a layout manager, I’m not sure if there’s an obvious way of implementing this. It isn’t obvious how things should behave in the two cases, and maybe that’s why the Android implementation is confusing – because they very problem it is solving has a confusing set of parameters.

      Anyway, since I have understood that the behaviour is different depending on your layout_width values, I’ve run in to far fewer issues with my layout weights.

      1. From the offical guide,it says:
        [Equally weighted children

        To create a linear layout in which each child uses the same amount of space on the screen, set the android:layout_height of each view to “0dp” (for a vertical layout) or the android:layout_width of each view to “0dp” (for a horizontal layout). Then set the android:layout_weight of each view to “1”.]
        And I’ve try to set layout_height=”0dp” instead,it works well,too. 😛
        Here is the link:http://developer.android.com/guide/topics/ui/layout/linear.html

Leave a Reply

Your email address will not be published. Required fields are marked *