Here’s an example
Let’s say that you have a horizontal linear layout with three buttons.
You assign a weight of 1 to two of the buttons and a weight of 2 to the third. The total weight for the linear layout is 4. The system will now divide the space up.
It allocates one quarter of the space to each of the buttons with a weight of 1. The remaining two quarters will be given to the button with a weight of 2.
All of the buttons are stretched to fill the space given to them.
It depends on the layout’s orientation
Linear layouts can be oriented:
- horizontally where its views are placed next to each other in rows
- vertically where its views are placed below each other in columns
Size and weight
A view’s size is determined by two attributes:
- layout_width – specifies the width of the view
- layout_height – specifies the height of the view
There are three ways that you can specify the dimensions for these attributes:
- match_parent – where the view’s width or height matches that of its parent container
- wrap_content – where the view’s width or height is only big enough to contain its contents
- you give a specific dimension, like 100dp for example
The layout_weight attribute
There is actually a fourth way that you can specify the size for a view, but only if its parent is a LinearLayout:
- layout_weight – how much space you allocate to the view
Calculating the calories
The system calculates the size of the view based on its layout width and height values when it builds the view.
Now, if you include the layout_weight attribute then the system has to calculate the width (or height) a second time, using the weight value to allocate space. It’s twice the work. This is why you should set the width or height attribute value to 0dp so there’s no extra calculation. The system then uses the weight attribute to do the calculation.
So depending on the orientation of the linear layout:
- horizontal linear layout parent – set the child view’s width to 0dp
- vertical linear layout parent – set the child view’s height to 0dp
If you don’t do this, not only are you making the system do extra work, but you may also get unexpected results (see the following examples).
Horizontal linear layout example
Here we have a parent vertical LinearLayout container.
It contains four child horizontal linear layouts, one below the other. Each of these four layouts contains three buttons in a row. The first two buttons are normal size buttons while the third is a small button.
Here’s the code for the first row of buttons:
Note the following:
We’ve set the layout_weight attribute value to 1 for each of the buttons. So they should all be the same size.
We’re using a horizontal linear layout so we should have set the layout_width attribute’s value to 0dp but we didn’t.
This will affect performance (though negligibly) as the system must make an extra width calculation for the button. You’ll also see the difference in the images below:
All other attribute values remain unchanged. Notice the difference between the size of the buttons in the top and second rows?
We’ve correctly set the layout_width attribute to 0dp for all of the buttons in the second row and the space is allocated correctly. The buttons are the same size.
The top row of buttons width attribute is set to wrap_content. The visual result is not quite what we wanted. The first two buttons are the same size while the small button is smaller.
The third row of buttons has no weight attribute and has their layout_width attributes set to wrap_content.
The bottom row of buttons has no weight attribute for the first two buttons whose layout_width attribute is set to wrap_content.
The small button has a weight value of 1 and its layout_width is set to 0dp. It therefore takes up all of the free space (the other two button’s weight is by default 0).
Compare the difference between the portrait and landscape views:
In the bottom row, the small button takes up all of the free space left by the other two buttons whose widths have been determined by the wrap_content value. These two buttons are the same size in both the portrait and landscape mode.
There is more free space in the landscape mode hence the small button expands to use all of this.
Vertical layout example
Here we have a horizontal parent linear layout container.
The sum of the weights
Its weightsum attribute’s value is set to 100. This is the total available space on the horizontal plane for this layout. We can then allocate portions of this to individual child views.
The parent linear layout contains three child vertical linear layouts. Their layout_weight attributes are each set to 33.333, so they each take up one-third of the horizontal space.
These child linear layout’s weightsum attributes are also set to 100.
Each child linear layout contains a button whose layout_weight attribute is set to 50, meaning that it should take up 50% of the available vertical space. As you can see from the images below, this is not the case for all of the buttons.
Each of these buttons attributes and settings are the same except for:
- the left button’s height is set to match_parent so it stretches to fill the entire space, ignoring the weight attribute
- the middle button’s height is set to wrap_content. The result is:
- a waste of resources as the system calculates the height twice, once using the height attribute and a second time using the weight attribute
- the button doesn’t quite take up 50% of the available space. In fact it takes up slightly more
- the right button’s height is set to 0dp. The button displays as expected, using 50% of the available height
Here’s the code for the left button:
We use the same attributes and values for the other two buttons except for the changes as described above.
I hope that you have found this tutorial helpful.
This project was created using Android Studio.
Are you using Eclipse or another IDE? Here's how you can use this project's Android Studio files.