Android Adventures - Layouts 2.3
Written by Mike James   
Thursday, 19 March 2015
Article Index
Android Adventures - Layouts 2.3
Units
LinearLayout
RelativeLayout
ConstraintLayout
Summary

LinearLayout

The next layout we need to consider is the LinearLayout.

This is a simple layout that can be used to do a great deal of the basic work of organizing a UI.  

In Android Studio LinearLayout occurs twice in the palette - once as a vertical and once as a horizontal LinearLayout. The difference, however, is just the setting of the orientation property to horizontal or vertical. In other words you can swap a horizontal and vertical linear layout with a simple property change. 

You can use a LinearLayout as the base Layout and replace the default RelativeLayout that Android Studio provides or you can place a LinearLayout within the RelativeLayout. 

Replacing one Layout with another isn't as easy as it sounds because you will lose all of the controls already positioned when you delete the first layout. If you edit the XML file to use a different layout then you might not lose the controls, but things get complicated if the new Layout doesn't support the same set of layout properties - which is usually the case. 

Android Studio really doesn't want you to use any Layout other than the RelativeLayout or ConstratingLayout as the initial container and so it doesn't let you delete it in an attempt to replace it. If you really want to use something else then you have no option but to edit the XML file directly.

The horizontal LinearLayout acts as a row container and a vertical LinearLayout acts as a column container. You can use nested LinearLayouts to build up something that looks like a table - but if this gets very complicated it is better to use a TableLayout. Nesting layouts like this is also inefficient at the rendering engine has to compute the layout multiple times to get it right. The advice is to use a ConstraintLayout and avoid nesting.  

If you place a LinearLayout on the RelativeLayout then you can position it like any other control. If you then place other controls inside it then they will stack up horizontally to form a row or vertically to form a column. 

This sounds easy but there are lots of ways to use a LinearLayout. 

For example, if you put a horizontal and a vertical LinearLayout in the RelativeLayout then how they behave depends on what you set their layout_width and layout_height to. If you set it to wrap_content then the two Layouts act like a horizontal and vertical panel of controls, i.e. you can move all of the controls as a block. 

 

linear4

 

It can be very difficult to be sure what you are dragging in the designer as it is easy to pickup one of the Buttons rather than the layout. Make use of the Component Tree to select the layout and to make sure that the Buttons are in the layout you think they are.

Things get more interesting when you nest one LinearLayout inside another to create a table.

For example, you can create a calculator style keypad by nesting three horizontal LinearLayouts inside a single vertical LinearLayout. That is, place a vertical LinearLayout on the screen and then place three horizontal LinearLayouts within it. Within each horizontal LinearLayout place three buttons. If you have difficulty doing this use the Component Tree window to make sure that the components are correctly nested. Make sure that you set the layout_width and layout_height to wrap_content otherwise the LinearLayouts will overlap. 

 

linear5

 

This is easier to arrange than using the RelativeLayout. The final Button is just placed into the vertical LinearLayout and it forms a row all of its own. 

There isn't much else to say about using LinearLayout apart from once you start using it then it tends to be the one you think of using far too often. It is very attractive to use a LinearLayout as a grouping device every time you need a row or column of controls. 

Layout_weight

There's one last mystery of the LinearLayout to discuss, layout_weight. 

This is a layout property that only the LinearLayout supports.

If you assign a layout_weight to any of the controls in a LinearLayout then the controls are adjusted in size to fill any unused space in proportion to their weights. 

The really important part of this description is "unused space". What happens is that Android first computes the layout ignoring any weight assignments. This means that the controls are set to the sizes you specified. Next the system determines what space remains unused in the containing LinearLayout. This is then distributed between the controls that have non-zero values of layout_weight in proportion to their weights. 

For example, suppose we have a horizontal LinearLayout with three Buttons all set to wrap_content. The screen has been rotated to provide a lot of unused space for the example:

 

weight1

 

You can see that there is a lot of unused space over to the right. If we now set the first Button's layout:weight to 1 it will be allocated all of that unused space:

weight2

 

If you now set the second Button's layout:weight to 1 then the unused space will be shared between the first two Buttons equally:

 

weight3

 

You can guess what would happen if we now set the third Button's layout:weight to 1 - the space would be shared equally and all three buttons would be the same size. If, however, the first button was given a weight of 2 then the unused space would be shared out in the ratio 2:1:1 and so on.

More interestingly what do you think would happen if you assigned a fixed width to the third Button? 

The answer is simple.

If the third Button's layout:weight is zero then it is set to the width specified and the other two buttons get the unused space - for example setting the third Button to 350dp gives:

weight4

 

However, if the third button has a layout:weight set then it will probably change its width because it gets a share of the unused space just like the other buttons. 

In other words, when you set a non-zero layout:weight a control can change its size even though you have set a specific size for it. 

This leads to the idea of "measured size" and "actual size". In the case of the third Button its measured size is 350dp but if its layout:weight is non-zero then its actual size on the screen will be different - it will use some of the unused space. 

When you are working with components in code the getWidth and getHeight properties will give you the actual width and height of the control. The getMeasuredWidth and getMeasuredHeight properties will give you the measured width and height before any adjustment by the Layout has been performed. 

Finally, it is worth pointing out that if you want to be sure that the three Buttons are the same size you have to set their widths to 0dp and weight to 1 (or the same value). 

Why is this necessary?

When you set the widths to zero all of the space is unused and the system will divided it equally between each one. 

You can also set their widths to some constant minimum value and then let the weight mechanism share out the unused space. 



Last Updated ( Monday, 27 March 2017 )