Search code examples
androidandroid-layoutpositionandroid-linearlayout

How to specify the side that an element is on in a linear layout?


I want two buttons side by side with the Add button being to the left of Remove button. These buttons are programmatically inserted. When only one button is there, it should take up all the space. So far, I have this:

<LinearLayout
   android:id="@+id/buttonLayout"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="horizontal">
   <include layout="@layout/add_button" />
   <include layout="@layout/remove_button" />
</LinearLayout>

The add button file:

<?xml version="1.0" encoding="utf-8"?>
<Button
    android:id="@+id/addAdditionalColors"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:onClick="addColor"
    android:text="@string/addMore"
    xmlns:android="http://schemas.android.com/apk/res/android" />

Remove button file:

<?xml version="1.0" encoding="utf-8"?>
<Button
    android:id="@+id/removeAdditionalColors"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="@string/remove"
    xmlns:android="http://schemas.android.com/apk/res/android" />

This works how I want. When one button is removed, the other one spans the whole width of the screen. However, let's say that I have the Remove button on the screen and am adding the Add button programmatically. It will be added to the right of Remove since it is added last. How do I avoid this, preferably in the XML file rather than removing both buttons and adding them in order using Java? Here is the desired position:

enter image description here

EDIT: I tried adding indexes when adding the View:

buttonLayout.addView(removeButton, 1);

and

buttonLayout.addView(addButton, 0);

The positioning is correct, but for some reason, not all space is filled up, even when I set the width of buttons to match_parent. Please check the video HERE.

Here is the full code that handles updating the buttons:

public void addColor(View view){
            //do stuff
            if(numColors == 4){
                removeView(findViewById(R.id.addAdditionalColors));
                //function above appears to work fine
            }
           else if(numColors == 3){
                final View removeButton = inflater.inflate(R.layout.remove_button, null);
                buttonLayout.addView(removeButton, 1);
            }
    }
    public void removeColor(View view){
        //do stuff
        if(numColors == 3) {
            final View addButton = inflater.inflate(R.layout.add_button, null);
            buttonLayout.addView(addButton, 0);
        }
        else if(numColors == 2){
            removeView(findViewById(R.id.removeAdditionalColors));
        }
    }

Solution

  • To add to the end of a LinearLayout:

    linearLayout.addView(view);
    

    To add to the beginning of a LinearLayout:

    linearLayout.addView(view, 0);
    

    The second addView() method above takes an index argument, and by passing 0 you're telling it that you want the new view to come "before" all others.

    Edit

    The reason your programmatically-added views aren't filling the whole width is that this behavior is a combination of three things:

    • "Stretching" in a LinearLayout is enabled by the layout_weight attribute
    • Your programmatically-inflated views use null as the parent argument
    • layout_ attributes are ignored when inflating without a parent

    The smallest change you could make to get everything to work would be to change this:

    final View removeButton = inflater.inflate(R.layout.remove_button, null);
    

    to this:

    final View removeButton = inflater.inflate(R.layout.remove_button, buttonLayout, false);
    

    By passing buttonLayout as the parent, your layout_weight attribute will be able to function correctly. You'd have to make a similar change for the "add" button too, of course.