coco
coco

Reputation: 3136

evenly spaced layout without nested weights

I realize this has been asked countless times, but I have yet to come up with a solution for myself. I want to make a simple set of buttons, laid out as below, without using GridLayout. I have also not had much luck with TableLayout or RelativeLayout. What does work for me, and well, is LinearLayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:padding="5dp" >

        <Button
            android:id="@+id/button1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#d0b0b0"
            android:paddingRight="10dp"
            android:textSize="15dip" />

        <View
            android:layout_width="10dp"
            android:layout_height="0dp"
            android:background="#808080" />

        <Button
            android:id="@+id/button2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#a09a09"
            android:textSize="15dip" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:padding="5dp" >

        <Button
            android:id="@+id/button3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#456456"
            android:padding="10dp"
            android:textSize="15dip" />
    </LinearLayout>

</LinearLayout>

But I'm getting warnings about "nested weights are bad for performance". Really? With such a simple layout? Can I ignore the warning? Is there some other (elegant?) way to do this?

LinearLayout, 3 buttons

Upvotes: 0

Views: 2744

Answers (3)

Nitesh Tiwari
Nitesh Tiwari

Reputation: 4762

Update: As we know the percent support library is deprecated from API level 26. ConstraintLayout is the new way to achieve the same flat xml structure.

Updated Github Project

Updated Samples:

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/fifty_thirty"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ffff8800"
        android:gravity="center"
        android:text="@string/fifty_fifty_text"
        android:textColor="@android:color/white"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintHeight_percent="0.5"
        android:textSize="25sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ffff5566"
        android:gravity="center"
        android:text="@string/fifty_fifty_text"
        android:textColor="@android:color/white"
        android:textSize="25sp"
        app:layout_constraintHeight_default="percent"
        app:layout_constraintHeight_percent="0.5"
        app:layout_constraintLeft_toRightOf="@id/fifty_thirty"
        app:layout_constraintTop_toBottomOf="@id/fifty_thirty"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5" />

</android.support.constraint.ConstraintLayout>

Deprecated Example

Update: We got the awesome solution by android support library to evenly divide our layout into percentage ratio.

Avoiding totally messy LinearLayout weights.

compile 'com.android.support:percent:23.0.0'

Code and concept

Github project

Consider this simple layout.

percent layout demo

<android.support.percent.PercentRelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/fifty_huntv"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ff7acfff"
        android:text="20% - 50%"
        android:textColor="@android:color/white"
        app:layout_heightPercent="20%"
        app:layout_widthPercent="50%" />
    <TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_toRightOf="@id/fifty_huntv"
        android:background="#ffff5566"
        android:text="80%-50%"
        app:layout_heightPercent="80%"
        app:layout_widthPercent="50%"
        />

</android.support.percent.PercentRelativeLayout>

Bingo we're done.Really awesome :-)

Upvotes: 3

coco
coco

Reputation: 3136

Another interesting detail about android layouts, that also has the effect of removing the lint warnings on nested weights. If I put my buttons into merge files thus:

<merge xmlns:android="http://schemas.android.com/apk/res/android" >

    <Button
        android:id="@+id/button1"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="#d0b0b0"
        android:textSize="15dip" />

</merge>

.. and do the same for the other buttons (and the spacer View that I made), and then include these merge xml files into the main xml file like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:padding="5dp" >

        <include layout="@layout/button1" />

        <include layout="@layout/spacer" />

        <include layout="@layout/button2" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:padding="5dp" >

        <include layout="@layout/button3" />
    </LinearLayout>

</LinearLayout>

.. I lose all the lint warnings! Is lint just missing the problem, or is it easier to inflate this way?

Not only does it make it easier to read (for me), it gives me lots of re-use possibilities. I <3 layout by XML!

Upvotes: -1

user
user

Reputation: 87064

You could avoid the nested layout warning with some adjustments to your current layout file:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="5dp" >

    <View
        android:id="@+id/anchor"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_centerVertical="true" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/anchor"
        android:layout_alignParentTop="true"
        android:padding="5dp" >

        <Button
            android:id="@+id/button1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#d0b0b0"
            android:paddingRight="10dp"            
            android:textSize="15dip" />

        <View
            android:layout_width="10dp"
            android:layout_height="0dp"
            android:background="#808080" />

        <Button
            android:id="@+id/button2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#a09a09"            
            android:textSize="15dip" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_below="@id/anchor"
        android:orientation="horizontal"
        android:padding="5dp" >

        <Button
            android:id="@+id/button3"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#456456"
            android:padding="10dp"            
            android:textSize="15dip" />
        <!-- textSize should be set in sp units, like 15sp -->
    </LinearLayout>

</RelativeLayout> 

Also, you might want to remove the LinearLayout that wraps the single Button(and add a 5dp margin to the Button).

Upvotes: 1

Related Questions