I want to know: What is android:weightSum and layout weight, and how do they work?
After some experimenting, I think the algorithm for LinearLayout is this:
Assume that weightSum
is set to a value. The case of absence is discussed later.
First, divide the weightSum
by the number of elements whith match_parent
or fill_parent
in the dimension of the LinearLayout (e.g. layout_width
for orientation="horizontal"
). We will call this value the weight multiplier for each element. The default value for
weightSum
is 1.0, so the default weight multiplier is 1/n
, where n
is the number of fill_parent
elements; wrap_content
elements do not contribute to n
.
E.g. when weightSum
is 60, and there are 3 fill_parent
elements, the weight multiplier is 20. The weight multiplier is the default value for e.g. layout_width
if the attribute is absent.
Second, the maximum possible expansion of every element is computed. First, the wrap_content
elements are computed according to their contents. Their expansion is deducted from the expansion of the parent container. We will call the remainer expansion_remainer
. This remainder is distributed among fill_parent
elements according to their layout_weight
.
Third, the expansion of every fill_parent
element is computed as:
Example:
If weightSum
is 60, and there are 3 fill_parent
elements with the weigths 10, 20 and 30, their expansion on the screen is 2/3, 1/3 and 0/3 of the parent container.
weight | expansion
0 | 3/3
10 | 2/3
20 | 1/3
30 | 0/3
40 | 0/3
The minimum expansion is capped at 0. The maximum expansion is capped at parent size, i.e. weights are capped at 0.
If an element is set to wrap_content
, its expansion is calculated first, and the remaining expansion is subject to distribution among the fill_parent
elements. If weightSum
is set, this leads to layout_weight
having no effect on wrap_content
elements.
However, wrap_content
elements can still be pushed out of the visible area by elements whose weight is lower than (e.g. between 0-1 for
weightSum
= 1 or between 0-20 for the above example).
If no weightSum
is specified, it is computed as the sum of all layout_weight
values, including elements with wrap_content
set! So having layout_weight
set on wrap_content
elements, can influence their expansion. E.g. a negative weight will shrink the other fill_parent
elements.
Before the fill_parent
elements are laid out, will the above formula be applied to wrap_content
elements, with maximum possible expansion being their expansion according to the wrapped content. The wrap_content
elements will be shrunk, and afterwards the maximum possible expansion for the remaining fill_parent
elements is computed and distributed.
This can lead to unintuitive results.