Nick Caballero
Nick Caballero

Reputation: 944

LinearLayout weights

I have two linear layouts that have the same width - one with two children and one with three. I'm trying to make the last two children the same width but I can't wrap my head around why Android behaves this way. I finally got it to look the way I want it to with the following weights:

Weights

Can anyone explain to me why this is working out this way?

I tried to do some simple math to figure out why. I'm guessing it's the sum of weights, minus the weight of the child, divided by the sum of weights, times the width of the parent. So:

sum = 1 + 6
((sum - 6) / sum) * W = 14.3% * W

I tried the same algorithm for the second row but it was totally off:

sum = 1 + 1 + 1.5
((sum - 1.5) / sum) * W = 57.1% * W

UPDATE

The above is true only when the child widths are set to match_parent. Setting width to 0, or 0dp, actually behaves as expected - greater weights lead to more space allocated for the child. The algorithm makes a little more sense now and works as expected for both rows.

sum = 1 + 6
(1 / sum) * W = 14.3% * W

Is the former behavior for weights with child widths set to match_parent by design? If so, what is the approximate algorithm for calculating the width of the children?

Upvotes: 1

Views: 928

Answers (3)

Viacheslav
Viacheslav

Reputation: 5593

According to your picture - weights are incorrect. E.g first "row": you have set first TextView with weight '1' and second weight is '6' - this means that second TextView will have more space - 6/7 of all layout width and first TextView have only 1/7. To simplify calculations imagine total width as 100(%) and divide them between views according to proportions which you want to give them.

Upvotes: -1

Streets Of Boston
Streets Of Boston

Reputation: 12596

First: Based on the look of your layout, it looks like you'd want to use a GridLayout instead of two LinearLayouts.

Back to your question: Don't set our layout_width to wrap_content (and especially not match_parent!) in your case. Set the layout_width to 0dp and let the layout_weight attribute distribute the available horzontal space.

The layout_weight attribute distributes/adds additional space to the specified layout_width (or layout_height for vertical oriented LinearLayouts). If you want only the layout_weight to contribute to the spacing, set layout_width to 0dp (layout_height to 0dp in case of vertically oriented LinearLayout).

Try this first and see if this behaves more to what you'd like and expect.

Try this example (where the grids are ratio 3:3:1):

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#FF0000FF" >

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="6"
        android:background="#FFFFFFFF"
        android:text="TextView" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="#FFFFFFFF"
        android:text="TextView" />
</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="3dp"
    android:background="#FF0000FF" >

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:background="#FFFFFFFF"
        android:text="TextView" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:background="#FFFFFFFF"
        android:text="TextView" />

<TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="#FFFFFFFF"
        android:text="TextView" />
</LinearLayout>

Upvotes: 1

Pavel Dudka
Pavel Dudka

Reputation: 20934

You can specify weightSum attribute for your LinearLayout in XML to let's say 1 for your first layout. Then your first 2 TextViews would get approx 0.9 and 0.1 weights (like 90% and 10%)

The same thing needs to be applied to the second LinearLayout. Something like:

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:weightSum="1"
        android:background="#FF0000FF" >

        <TextView
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight=".9"
            android:layout_margin="3dp"
            android:background="#FFFFFFFF"
            android:text="TextView" />

        <TextView
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight=".1"
            android:layout_margin="3dp"
            android:background="#FFFFFFFF"
            android:text="TextView" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="3dp"
        android:weightSum="1"
        android:background="#FF0000FF" >

        <TextView
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_margin="3dp"
            android:layout_weight=".45"
            android:background="#FFFFFFFF"
            android:text="TextView" />

        <TextView
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight=".45"
            android:layout_margin="3dp"
            android:background="#FFFFFFFF"
            android:text="TextView" />

        <TextView
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight=".1"
            android:layout_margin="3dp"
            android:background="#FFFFFFFF"
            android:text="TextView" />
    </LinearLayout>

BTW, don't forget to set your width attributes to 0dip

Upvotes: 1

Related Questions