user3199577
user3199577

Reputation: 249

Adding Views to a LinearLayout Android

I have Vertical ScrollView where I am going to add some Views after a buttonClick. Here is the xml of the scroll view

<ScrollView
    android:background = "@drawable/border"
    android:layout_weight="31"
    android:id="@+id/scrollView1"
    android:layout_width="match_parent"
    android:layout_height="0dp" >

    <LinearLayout
        android:id="@+id/layoutScroll"
        android:padding = "10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >






        <LinearLayout
            android:id="@+id/layoutContainer"
            android:padding="5dp"
            android:orientation="vertical"
            android:background="@drawable/border_2"
            android:layout_width="fill_parent"
            android:layout_height = "wrap_content">

            <RelativeLayout
                android:id="@+id/relativeLayout"
                android:layout_height = "wrap_content"
                android:layout_width = "fill_parent">
                <TextView
                    android:id="@+id/textWord"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@string/word"
                    android:textAppearance="?android:attr/textAppearanceMedium" />

                <TextView
                    android:id="@+id/textNumber"
                    android:background = "@drawable/border_1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:layout_alignParentTop="true"
                    android:text=" 1 "
                    android:textAppearance="?android:attr/textAppearanceMedium" />

            </RelativeLayout>

            <EditText 
                android:id="@+id/editWord"
                android:layout_marginTop="3dp"
                android:layout_gravity="left"
                android:inputType="text"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:lines="1"
                android:scrollbars="horizontal"/>
            <TextView 
                android:id="@+id/textDefinition"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text = "@string/definition" />
            <EditText 
                android:id="@+id/editDefinition"
                android:gravity="top|left"
                android:inputType="textMultiLine"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:lines="3"
                android:maxLines="3"
                android:scrollbars="vertical"/>               
        </LinearLayout>
        <TextView
            android:id="@+id/textEmpty"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:lines="1"
            android:textAppearance="?android:attr/textAppearanceMedium" />





    </LinearLayout>
</ScrollView>

In this function I create the same objects for adding them to the LinearLayout

private void initInterface (){
    layoutScroll = (LinearLayout) findViewById (R.id.layoutScroll);
    layoutContainer = new LinearLayout(getApplicationContext());
    relativeLayout = new RelativeLayout(getApplicationContext());

    textWord = new TextView(getApplicationContext());
    textDefinition= new TextView(getApplicationContext());
    textNumber = new TextView(getApplicationContext());
    textEmpty = new TextView(getApplicationContext());

    editWord = new EditText(getApplicationContext());
    editDefinition = new EditText(getApplicationContext());


    layoutContainer.setPadding(5, 5, 5, 5);
    layoutContainer.setOrientation(LinearLayout.VERTICAL);
    layoutContainer.setBackgroundResource(R.drawable.border_2);
    LinearLayout.LayoutParams param1 = 
            new LayoutParams(LayoutParams.MATCH_PARENT , LayoutParams.WRAP_CONTENT );
    layoutContainer.setLayoutParams(param1);


    RelativeLayout.LayoutParams param2 = 
            new RelativeLayout.LayoutParams (RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    relativeLayout.setLayoutParams(param2);
    textWord.setLayoutParams(param2);
    textWord.setTextAppearance(this,android.R.style.TextAppearance_Medium);
    textWord.setText("Word:");

    RelativeLayout.LayoutParams param3= 
            new RelativeLayout.LayoutParams 
            (RelativeLayout.LayoutParams.WRAP_CONTENT, 
                    RelativeLayout.LayoutParams.WRAP_CONTENT);
    param3.addRule(RelativeLayout.ALIGN_PARENT_TOP);
    param3.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
    textNumber.setBackgroundResource(R.drawable.border_1);
    textNumber.setTextAppearance(this,android.R.style.TextAppearance_Medium);
    textNumber.setLayoutParams(param3);

    relativeLayout.addView(textWord);
    relativeLayout.addView(textNumber);


    LinearLayout.LayoutParams param4 = param1;
    param4.setMargins(0, 3, 0, 0);
    editWord.setGravity(Gravity.LEFT);
    editWord.setTextAppearance(this,android.R.style.TextAppearance_Medium);
    editWord.setLines(1);
    editWord.setHorizontallyScrolling(true);
    editWord.setLayoutParams(param4);


    textDefinition.setLayoutParams(param1);
    textDefinition.setTextAppearance(this,android.R.style.TextAppearance_Medium);
    textDefinition.setText("Definition:");

    editDefinition.setGravity(Gravity.TOP | Gravity.LEFT);
    editDefinition.setSingleLine(false);
    editDefinition.setLayoutParams(param1);
    editDefinition.setMaxLines(3);
    editDefinition.setLines(3);
    editDefinition.setVerticalScrollBarEnabled(true);
    editDefinition.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);

    textEmpty.setTextAppearance(this,android.R.style.TextAppearance_Medium);
    textEmpty.setLines(1);
    textEmpty.setLayoutParams(param1);

    layoutContainer.addView(relativeLayout);
    layoutContainer.addView(editWord);
    layoutContainer.addView(textDefinition);
    layoutContainer.addView(editDefinition);




}

And then I add them to the Layout like this.

public void onCLick_Add(View v){
    layoutScroll.addView(layoutContainer);
    layoutScroll.addView(textEmpty);

}

The problem is that It only workd once . When I click the button for the second time the app crashes. Thank you in advance.

Upvotes: 0

Views: 1502

Answers (3)

droidx
droidx

Reputation: 2172

As I pointed out in the comment, the bug is this : Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

Checklist for these kind of bugs.

As pointed out in this post the specified child already has a parent

Double check all your addView calls.

  • Make sure not to add any view more then once. When a View is allready used (e.g., you got it with findViewById, don't use addView on it.

  • When you want to add a view, use addView with a NEW view. You can add several of these new views to one view, but you cannot add that one view multiple times.

  • You can't re-use a view simply by changing some stuff. You CAN re-use a variable, but you need to make a new view if you want to re-add it using addView.

Upvotes: 0

Chrisport
Chrisport

Reputation: 3146

Your log says:

Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

You are trying to add same layoutContainer and textEmpty multiple times when clicking multiple times. This fails because they are already added and therefore already have a parent. (You cannot add same View to more then one parent)

Solution I guess you want to create a new View every time you press the button and add this to your layoutScroll. You should call your init-method again for every click:

public void onCLick_Add(View v){
  initInterface();
  layoutScroll.addView(layoutContainer);
  layoutScroll.addView(textEmpty);
}

I would also suggest to divide initInterface() into:

private View createLayoutContainer();
private View createTextEmpty();

Make sure you take initialization of scrollView outside (e.g. onCreate) and you declare views like layoutContainer localy in the createLayoutContainer() instead of globally.

Here a snippet how it would look:

private View createLayoutContainer(){
  LinearLayout layoutContainer = new LinearLayout(getApplicationContext());
  RelativeLayout relativeLayout = new RelativeLayout(getApplicationContext());

  TextView textWord = new TextView(getApplicationContext());
  ...
  return layoutContainer;
}

public void onCLick_Add(View v){
  layoutScroll.addView(createLayoutContainer());
  layoutScroll.addView(createTextEmptyView());
}

Upvotes: 1

Rohan Kandwal
Rohan Kandwal

Reputation: 9326

The problem occurs due to the fact that a ScrollView can only have on child View. In other words, a ScrollView can have a LinearLayout or a RelativeLayout or a TextView etc. Update your code such that new views inside are added inside LinearLayout (layoutScroll) instead of ScrollView.

Upvotes: 0

Related Questions