41

I am trying to create a layout where I need to add table rows dynamically. Below is the table layout xml

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/displayLinear"
    android:background="@color/background_df"
    android:orientation="vertical" >

         <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/display_row"
            android:layout_marginTop="280dip" >

</TableLayout>

The activity file where rows are being added dynamically is

public void init(){
    menuDB = new MenuDBAdapter(this);
    ll = (TableLayout) findViewById(R.id.displayLinear);

    TableRow row=(TableRow)findViewById(R.id.display_row);
    for (int i = 0; i <2; i++) {

        checkBox = new CheckBox(this);
        tv = new TextView(this);
        addBtn = new ImageButton(this);
        addBtn.setImageResource(R.drawable.add);
        minusBtn = new ImageButton(this);
        minusBtn.setImageResource(R.drawable.minus);
        qty = new TextView(this);
        checkBox.setText("hello");
        qty.setText("10");
        row.addView(checkBox);
        row.addView(minusBtn);
        row.addView(qty);
        row.addView(addBtn);
        ll.addView(row,i);

    }
}

But when I run this, I am getting below error

08-13 16:27:46.437: E/AndroidRuntime(23568): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.roms/com.example.roms.DisplayActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

I understand that this is due to command ll.addView(row,i); but when I remove this its adding all stuff in a single row rather tan creating a new row for next item. I tried with giving index too as row.addView(addBtn,i) but still its not populating correctly. Please advise. Thanks.

juhan_h
  • 3,965
  • 4
  • 29
  • 35
user2416087
  • 423
  • 1
  • 6
  • 6
  • Here Table row is already in xml file...So before you add programmatically you should call ll.removeallViews() method. – Piyush Aug 13 '13 at 11:10

8 Answers8

89

Create an init() function and point the table layout. Then create the needed rows and columns.

   public void init() {
            TableLayout stk = (TableLayout) findViewById(R.id.table_main);
            TableRow tbrow0 = new TableRow(this);
            TextView tv0 = new TextView(this);
            tv0.setText(" Sl.No ");
            tv0.setTextColor(Color.WHITE);
            tbrow0.addView(tv0);
            TextView tv1 = new TextView(this);
            tv1.setText(" Product ");
            tv1.setTextColor(Color.WHITE);
            tbrow0.addView(tv1);
            TextView tv2 = new TextView(this);
            tv2.setText(" Unit Price ");
            tv2.setTextColor(Color.WHITE);
            tbrow0.addView(tv2);
            TextView tv3 = new TextView(this);
            tv3.setText(" Stock Remaining ");
            tv3.setTextColor(Color.WHITE);
            tbrow0.addView(tv3);
            stk.addView(tbrow0);
            for (int i = 0; i < 25; i++) {
                TableRow tbrow = new TableRow(this);
                TextView t1v = new TextView(this);
                t1v.setText("" + i);
                t1v.setTextColor(Color.WHITE);
                t1v.setGravity(Gravity.CENTER);
                tbrow.addView(t1v);
                TextView t2v = new TextView(this);
                t2v.setText("Product " + i);
                t2v.setTextColor(Color.WHITE);
                t2v.setGravity(Gravity.CENTER);
                tbrow.addView(t2v);
                TextView t3v = new TextView(this);
                t3v.setText("Rs." + i);
                t3v.setTextColor(Color.WHITE);
                t3v.setGravity(Gravity.CENTER);
                tbrow.addView(t3v);
                TextView t4v = new TextView(this);
                t4v.setText("" + i * 15 / 32 * 10);
                t4v.setTextColor(Color.WHITE);
                t4v.setGravity(Gravity.CENTER);
                tbrow.addView(t4v);
                stk.addView(tbrow);
            }

        }

Call init function in your onCreate method:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);

        init();
    }

Layout file like:

 <ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#3d455b"
        android:layout_alignParentLeft="true" >

        <HorizontalScrollView
            android:id="@+id/hscrll1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" >

            <RelativeLayout
                android:id="@+id/RelativeLayout1"
                android:layout_width="fill_parent"
                android:layout_gravity="center"
                android:layout_height="fill_parent"
                android:orientation="vertical" >

                <TableLayout
                    android:id="@+id/table_main"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerHorizontal="true" >
                </TableLayout>
            </RelativeLayout>
        </HorizontalScrollView>
    </ScrollView>

Will look like:

enter image description here

Vettiyanakan
  • 7,957
  • 6
  • 37
  • 55
  • One issue is coming with this solution. Every time i click on the app new rows are being appended rather being fresh new 25 lines. For example, if i click 1st time 25 rows being shown, in the next click its 50 lines now and so on.. How to clear the previous 25 line and add new 25 line on each click? – sameer pradhan Feb 01 '21 at 10:38
  • @sameerpradhan one way you can do it by storing the rows in an array and when you want to change the content remove the contents of that array and call init again – Vettiyanakan Feb 02 '21 at 07:28
66

You shouldn't be using an item defined in the Layout XML in order to create more instances of it. You should either create it in a separate XML and inflate it or create the TableRow programmaticaly. If creating them programmaticaly, should be something like this:

    public void init(){
    TableLayout ll = (TableLayout) findViewById(R.id.displayLinear);


    for (int i = 0; i <2; i++) {

        TableRow row= new TableRow(this);
        TableRow.LayoutParams lp = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT);
        row.setLayoutParams(lp);
        checkBox = new CheckBox(this);
        tv = new TextView(this);
        addBtn = new ImageButton(this);
        addBtn.setImageResource(R.drawable.add);
        minusBtn = new ImageButton(this);
        minusBtn.setImageResource(R.drawable.minus);
        qty = new TextView(this);
        checkBox.setText("hello");
        qty.setText("10");
        row.addView(checkBox);
        row.addView(minusBtn);
        row.addView(qty);
        row.addView(addBtn);
        ll.addView(row,i);
    }
}
photonbit
  • 676
  • 5
  • 2
  • 3
    Notice that you should set the correct LayoutParams to fit the description in your XML, in the example isn't complete for you to make some research :) – photonbit Aug 13 '13 at 12:03
10

You also can, as Fredigato said, declare a RelativeLayout in a separate Layout file. Then instantiate it using:

for(int i = 0; i < 6; i ++){
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService
                (Context.LAYOUT_INFLATER_SERVICE);
RelativeLayout row = (RelativeLayout) inflater.inflate(R.layout.table_view,null);
        quizesTableLayout.addView(row,i);
}

In this approach you can easily design one custom row using XML and reuse it.

Now, to be able to change the children views in the instantiated RelativeLayout. You can call row.childAt(index).

So lets say you have a TextView in the RelativeLayout, you can use:

TextView tv = (TextView) row.childAt(0);
tv.setText("Text");
Essam Ewaisha
  • 439
  • 5
  • 15
4

change code of init like following,

public void init(){
    menuDB = new MenuDBAdapter(this);
    ll = (TableLayout) findViewById(R.id.displayLinear);
    ll.removeAllViews()

    for (int i = 0; i <2; i++) {
        TableRow row=(TableRow)findViewById(R.id.display_row);
        checkBox = new CheckBox(this);
        tv = new TextView(this);
        addBtn = new ImageButton(this);
        addBtn.setImageResource(R.drawable.add);
        minusBtn = new ImageButton(this);
        minusBtn.setImageResource(R.drawable.minus);
        qty = new TextView(this);
        checkBox.setText("hello");
        qty.setText("10");
        row.addView(checkBox);
        row.addView(minusBtn);
        row.addView(qty);
        row.addView(addBtn);
        ll.addView(row,i);

    }
mdDroid
  • 3,135
  • 2
  • 22
  • 34
  • Thanks. I tried as suggested but now getting null point exception.08-13 16:56:14.727: E/AndroidRuntime(25623): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.roms/com.example.roms.DisplayActivity}: java.lang.NullPointerException – user2416087 Aug 13 '13 at 11:27
  • have u initialise your all views initially – mdDroid Aug 13 '13 at 11:30
1
Activity
    <HorizontalScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TableLayout
            android:id="@+id/mytable"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </TableLayout>
    </HorizontalScrollView>

Your Class

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_testtable);
    table = (TableLayout)findViewById(R.id.mytable);
    showTableLayout();
}


public  void showTableLayout(){
    Date date = new Date();
    int rows = 80;
    int colums  = 10;
    table.setStretchAllColumns(true);
    table.bringToFront();

    for(int i = 0; i < rows; i++){

        TableRow tr =  new TableRow(this);
        for(int j = 0; j < colums; j++)
        {
            TextView txtGeneric = new TextView(this);
            txtGeneric.setTextSize(18);
            txtGeneric.setText( dateFormat.format(date) + "\t\t\t\t" );
            tr.addView(txtGeneric);
            /*txtGeneric.setHeight(30); txtGeneric.setWidth(50);   txtGeneric.setTextColor(Color.BLUE);*/
        }
        table.addView(tr);
    }
}
Irving
  • 11
  • 1
1

You can use an inflater with TableRow:

for (int i = 0; i < months; i++) {
    
    View view = getLayoutInflater ().inflate (R.layout.list_month_data, null, false);
        
    TextView textView = view.findViewById (R.id.title);
    
    textView.setText ("Text");
        
    tableLayout.addView (view);
    
}

Layout:

<TableRow
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_centerInParent="true"
    android:gravity="center_horizontal"
    android:paddingTop="15dp"
    android:paddingRight="15dp"
    android:paddingLeft="15dp"
    android:paddingBottom="10dp"
    >
    
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:gravity="center"
        />
    
</TableRow>
Acuna
  • 1,741
  • 17
  • 20
0
public Boolean addArtist(String artistName){

        SQLiteDatabase db= getWritableDatabase();

        ContentValues data=new ContentValues();
        data.put(ArtistMaster.ArtistDetails.COLUMN_ARTIST_NAME,artistName);
        long id = db.insert(ArtistMaster.ArtistDetails.TABLE_NAME,null,data);

        if(id>0){
            return true;
        }else{
            return false;
        }
    }
Amir Dora.
  • 2,831
  • 4
  • 40
  • 61
0

I am trying the above code with modification as per my requirement. The table is created properly. Bu the problem is when I am opening the activity 1st time, the table is not displaying. It is displaying 2nd time only.

My code is

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_aggre_ascendingorder);
        drawerLayout = findViewById(R.id.drawer_layout);
        init();
    }

    @SuppressLint("ResourceType")
    public void init() {
        stk = (TableLayout) findViewById(R.id.table_main);
        TableRow tbrow0 = new TableRow(this);
        TextView tv0 = new TextView(this);
        tv0.setText("Actual Values ");
        tv0.setWidth(330);
        tv0.setGravity(Gravity.CENTER);
        tv0.setTextColor(Color.WHITE);
        tv0.setTextSize(12);
        tv0.setBackgroundResource(R.drawable.border4);
        tbrow0.addView(tv0);
        TextView tv1 = new TextView(this);
        tv1.setText("Meter Values ");
        tv1.setWidth(330);
        tv1.setGravity(Gravity.CENTER);
        tv1.setTextColor(Color.WHITE);
        tv1.setTextSize(12);
        tv1.setBackgroundResource(R.drawable.border4);
        tbrow0.addView(tv1);
        TextView tv2 = new TextView(this);
        tv2.setText("Error ");
        tv2.setWidth(315);
        tv2.setGravity(Gravity.CENTER);
        tv2.setTextColor(Color.WHITE);
        tv2.setTextSize(12);
        tv2.setBackgroundResource(R.drawable.border4);
        tbrow0.addView(tv2);

        Intent z = getIntent();
        input1 = z.getIntExtra(EDIT, 1);
        input2 = z.getIntExtra(TEXT, 1);

        if (input2 == 0) {
            x = 400;
        } else {
            x = input1 / input2;
        }

        stk.addView(tbrow0);
        try {
            for (int i = 0; i < x + 1; i++) {
                TableRow tbrow = new TableRow(this);
                final EditText t1v = new EditText(this);
                t1v.setId(1);
                if (input2 == 0) {
                    t1v.setHint("");
                } else {
                    t1v.setText("" + i * input2);
                }
                final EditText t2v;
                TextView t3v = null;
                t1v.setTextColor(Color.BLACK);
                t1v.setGravity(Gravity.CENTER);
                t1v.setTextSize(12);
                t1v.setInputType(InputType.TYPE_CLASS_NUMBER);
                t1v.setBackgroundResource(R.drawable.border);


                t2v = new EditText(this);
                t2v.setHint("");
                t2v.setTextColor(Color.BLACK);
                t2v.setGravity(Gravity.CENTER);
                t2v.setTextSize(12);
                t2v.setInputType(InputType.TYPE_CLASS_NUMBER);
                t2v.setBackgroundResource(R.drawable.border);


                t3v = new TextView(this);
                t3v.setHint("");
                t3v.setTextColor(Color.BLACK);
                t3v.setGravity(Gravity.CENTER);
                t3v.setTextSize(12);
                t3v.setBackgroundResource(R.drawable.border);

                String stb = "0,0,0";

                if((Integer.parseInt(Prefs.getString("aggasstabLength",""))-1) > i){
                    stb = Prefs.getString("aggasstabVal_" + (i + 1), "");
                }
                //t1v.setText(stb.split(",")[0]);
                t2v.setText(stb.split(",")[1]);
                t3v.setText(stb.split(",")[2]);
                tbrow.addView(t1v);
                tbrow.addView(t2v);
                tbrow.addView(t3v);
                stk.addView(tbrow);
`

Can you clear me what is the mistake I am doing on this