Question

I have a problem in Android creating a table adding rows dynamically. The error message is:

The specified child already has a parent. You must call removeView() on the child's parent first

But why?

    void setCalendario(List<ArrayList<String>> l){
    TableLayout table = (TableLayout)findViewById(R.id.list_tableLayout1);
    TableRow tr = new TableRow(this);
    tr.removeAllViews();
    tr.setPadding(0,10,0,10);
    tr.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
    TextView tv_item1 = new TextView(this);
    TextView tv_item2 = new TextView(this);
    TextView tv_item3 = new TextView(this);
    for (ArrayList<String> al : l){
        int i = 0;
        for(String s : al){
            if (i == 0){
                i++;
                tv_item1.setText(s);
                tv_item1.setGravity(Gravity.CENTER);
            }
            if (i == 1){
                tv_item2.setText(s);
                tv_item2.setGravity(Gravity.CENTER);
                i++;
            }
            if (i == 2){
                tv_item3.setText(s);
                tv_item3.setGravity(Gravity.CENTER);
                tr.addView(tv_item1);
                tr.addView(tv_item2);
                tr.addView(tv_item3);
                table.addView(tr, new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
            }
        }
    }

    }

the xml code:

   <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.MSca.gorhinos.Calendario$PlaceholderFragment" >

    <TableLayout
    android:id="@+id/list_tableLayout1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:stretchColumns="0,1,2,3" >

<TableRow
    android:id="@+id/tableRow1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

<TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:textColor="#000000"/>

<TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:textColor="#000000"/>

<TextView
                android:id="@+id/textView3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:textColor="#000000"/>


</TableRow>
</TableLayout>

</RelativeLayout>
Was it helpful?

Solution

So, you once create tv_item1, tv_item2 and tv_item3. Then in cycle for all ArrayList you adding this views

tr.addView(tv_item1);
tr.addView(tv_item2);
tr.addView(tv_item3);

At the second iteration you already add tv_item1 to tr. And you want to do it again. I guess you need just transfer this lines to cycle:

TableRow tr = new TableRow(this);
tr.removeAllViews();
tr.setPadding(0,10,0,10);
tr.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
TextView tv_item1 = new TextView(this);
TextView tv_item2 = new TextView(this);
TextView tv_item3 = new TextView(this);

OTHER TIPS

You're using a for-loop to add the same references to TextViews to your TableRow. So in the next iteration of the loop, the same objects are added to the TableRow (or TableLayout), again! They already have a parent by then.

Try to initialize the TableRow and TextView objects inside the (outer)for-loop.

EDIT: Modified your code.

void setCalendario(List<ArrayList<String>> l) {
    // Here we initialize the objects we re-initialize every iteration of the loop
    TableLayout table = (TableLayout)findViewById(R.id.list_tableLayout1);
    for (ArrayList<String> al : l) {
        TableRow tr = new TableRow(this);
    // I can't believe a freshly initialized TableRow object has views attached...
        tr.removeAllViews();
        tr.setPadding(0,10,0,10);
    // Not sure why these layout params are needed already, as they are specified
    // when adding this TableRow to the TableLayout object as well.
        tr.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
        TextView tv_item1 = new TextView(this);
        TextView tv_item2 = new TextView(this);
        TextView tv_item3 = new TextView(this);
        int i = 0;
        for(String s : al) {
            if (i == 0) {
                i++;
                tv_item1.setText(s);
                tv_item1.setGravity(Gravity.CENTER);
            }
            if (i == 1) {
                tv_item2.setText(s);
                tv_item2.setGravity(Gravity.CENTER);
                i++;
            }
            if (i == 2) {
                tv_item3.setText(s);
                tv_item3.setGravity(Gravity.CENTER);
                tr.addView(tv_item1);
                tr.addView(tv_item2);
                tr.addView(tv_item3);
                table.addView(tr, new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
            }
        }
    }
    } 

because you are trying to put the same textView many times. you can use it only once, so you have to instantiate it again and again :

// you remove the definition of the text views here and you put it inside the loop
    for (ArrayList<String> al : l){
        int i = 0;
        for(String s : al){
 TextView tv_item2 = new TextView(this);
TextView tv_item1 = new TextView(this);
TextView tv_item3 = new TextView(this);
            if (i == 0){
                i++;

                tv_item1.setText(s);
                tv_item1.setGravity(Gravity.CENTER);
            }
            if (i == 1){

                tv_item2.setText(s);
                tv_item2.setGravity(Gravity.CENTER);
                i++;
            }
            if (i == 2){

                tv_item3.setText(s);
                tv_item3.setGravity(Gravity.CENTER);
                tr.addView(tv_item1);
                tr.addView(tv_item2);
                tr.addView(tv_item3);
                table.addView(tr, new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
            }
        }
    }

This is not the best way to do it, you should may be creat a methode that takes your "i" as parameter and returns a TextView (with gravity center ... and your staff).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top