6

I am trying to load the data retrieve from SQLite database into Android tableLayout. Here is my code:

TableLayout table_layout;
private SQLiteDatabase mDb;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.tabhost);

    new Handler().post(new Runnable() { 
        @Override 
        public void run() { 
            DatabaseAdapter dbAdapter = new DatabaseAdapter(Exercise.this); 
            dbAdapter.createDatabase();
            Exercise.this.mDb =  new DataBaseHelper(Exercise.this).getReadableDatabase();  
            table_layout = (TableLayout) findViewById(R.id.TableLayout);
            BuildTable();
        }
    });
}

private void BuildTable() {
    try {
        String sql = "SELECT exerciseType FROM exercise";
        Cursor mCur = mDb.rawQuery(sql, null);
        if (mCur.getCount() != 0) {
            if (mCur.moveToFirst()) {
                do {
                    int rows = mCur.getCount();
                    int cols = mCur.getColumnCount();
                    // outer for loop
                    for (int i = 0; i < rows; i++) {

                        TableRow row = new TableRow(this);
                        row.setLayoutParams(new LayoutParams(
                                LayoutParams.MATCH_PARENT,
                                LayoutParams.WRAP_CONTENT));

                        // inner for loop
                        for (int j = 0; j < cols; j++) {

                            TextView tv = new TextView(this);
                            tv.setLayoutParams(new LayoutParams(
                                    LayoutParams.WRAP_CONTENT,
                                    LayoutParams.WRAP_CONTENT));
                            tv.setGravity(Gravity.CENTER);
                            tv.setTextSize(18);
                            tv.setPadding(0, 5, 0, 5);

                            tv.setText(mCur.getString(j));
                            row.addView(tv);                            

                        }
                        table_layout.addView(row);
                    }
                } while (mCur.moveToNext());
            }
        }
    } catch (SQLException mSQLException) {
        throw mSQLException;
    }
}

When I print out the mCur.getString(j), it did returning me the string. However, it does not appear in the tableLayout or showing me any error message. I wonder why is it so.

Edited portion

for (int j = 0; j < cols + 1; j++) {
                        TextView tv = new TextView(this);
                        tv.setLayoutParams(new TableRow.LayoutParams(
                                TableLayout.LayoutParams.MATCH_PARENT,
                                LayoutParams.WRAP_CONTENT));
                        tv.setGravity(Gravity.CENTER);
                        tv.setTextSize(18);
                        tv.setPadding(0, 5, 0, 5);
                        tv.setText(mCur.getString(j));

                        row.addView(tv);
                        if(j == cols){
                            CheckBox cb = new CheckBox(this);
                            cb.setLayoutParams(new TableRow.LayoutParams(
                                    TableLayout.LayoutParams.MATCH_PARENT,
                                    LayoutParams.WRAP_CONTENT));
                            cb.setGravity(Gravity.CENTER);
                            cb.setPadding(0, 5, 0, 5);
                            row.addView(cb);
                        }

                    }

Edited Portion

private void BuildTable() {
    try {
        String sql = "SELECT * FROM exercise";
        Cursor mCur = mDb.rawQuery(sql, null);
        if (mCur.getCount() != 0) {
            if (mCur.moveToFirst()) {

                TableRow row = new TableRow(this);
                row.setLayoutParams(new LayoutParams(
                        TableLayout.LayoutParams.MATCH_PARENT,
                        LayoutParams.WRAP_CONTENT));

                TextView tv1 = new TextView(this);
                tv1.setLayoutParams(new TableRow.LayoutParams(
                        TableLayout.LayoutParams.MATCH_PARENT,
                        LayoutParams.WRAP_CONTENT));
                tv1.setGravity(Gravity.LEFT);
                tv1.setTextSize(10);
                tv1.setText("ID");
                row.addView(tv1);

                TextView tv2 = new TextView(this);
                tv2.setLayoutParams(new TableRow.LayoutParams(
                        TableLayout.LayoutParams.MATCH_PARENT,
                        LayoutParams.WRAP_CONTENT));
                tv2.setGravity(Gravity.LEFT);
                tv2.setTextSize(10);
                tv2.setText("Exercise Type");
                row.addView(tv2);

                TextView tv3 = new TextView(this);
                tv3.setLayoutParams(new TableRow.LayoutParams(
                        TableLayout.LayoutParams.MATCH_PARENT,
                        LayoutParams.WRAP_CONTENT));
                tv3.setGravity(Gravity.LEFT);
                tv3.setTextSize(10);
                tv3.setText("Amount");
                row.addView(tv3);

                TextView tv4 = new TextView(this);
                tv4.setLayoutParams(new TableRow.LayoutParams(
                        TableLayout.LayoutParams.MATCH_PARENT,
                        LayoutParams.WRAP_CONTENT));
                tv4.setGravity(Gravity.LEFT);
                tv4.setTextSize(10);
                tv4.setText("");
                row.addView(tv4);

                do {
                    int cols = mCur.getColumnCount();

                    for (int j = 0; j < cols + 1; j++) {
                        if (j == cols) {
                            CheckBox cb = new CheckBox(this);
                            cb.setLayoutParams(new TableRow.LayoutParams(
                                    TableLayout.LayoutParams.MATCH_PARENT,
                                    LayoutParams.WRAP_CONTENT));
                            cb.setGravity(Gravity.LEFT);
                            row.addView(cb);
                            final int k = j;
                            cb.setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    exerciseIDList.add(Integer.toString(k));
                                }
                            });
                            break;
                        }

                        TextView tv = new TextView(this);
                        tv.setLayoutParams(new TableRow.LayoutParams(
                                TableLayout.LayoutParams.MATCH_PARENT,
                                LayoutParams.WRAP_CONTENT));
                        tv.setGravity(Gravity.LEFT);
                        tv.setTextSize(10);
                        tv.setText(mCur.getString(j));

                        row.addView(tv);

                    }
                    table_layout.addView(row);
                } while (mCur.moveToNext());
            }
        }
    } catch (SQLException mSQLException) {
        throw mSQLException;
    }

}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • 1
    Use the proper `LayoutParams`. – user Jul 30 '14 at 08:28
  • @Luksprog Would you mind to provide some example which can fit into my situation? –  Jul 30 '14 at 09:35
  • Your TableRows have as parent a TableLayout so their LayoutParams should be of that type. So when you do `row.setLayoutParams(new LayoutParam(...` you should be doing `row.setLayoutParams(new TableLayout.LayoutParam(TableLayout.LayoutParam.MATCH_PARENT...)`. You should always use the LayoutParams of the proper class. The same goes for your TextViews, their are children of a TableRow so use TableRow.Layoutparams. – user Jul 30 '14 at 10:39
  • @Luksprog So basically I just add in the line of codes? Do I need to change anything in the layout.xml? –  Jul 30 '14 at 11:56
  • Yeap, just make the changes I've said in the comment above, no modifications, and see what happens. – user Jul 30 '14 at 12:00
  • It works! Thanks a lot! Would you mind to post it as answer so I can mark it? –  Jul 30 '14 at 12:12

1 Answers1

5

You're not using the proper LayoutParams for the views that you programmatically add to the TableLayout. The created TableRows will be added to the TableLayout so their LayoutParams should be of type TableLayout.LayoutParams:

row.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));

The same goes for the row TextViews, which should use TableRow.LayoutParams:

tv.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT));
user
  • 86,916
  • 18
  • 197
  • 190
  • Thanks a lot! It works! But do you have any idea to add checkbox to each row dynamically? Because from what I am doing, I am getting checkbox added to each row and column –  Jul 30 '14 at 12:20
  • @20Cents Make `j` go to `cols + 1`, this way you'll have one extra column added. In the for loop you'll then insert `if (j == cols) {// add the CheckBox}`. This way you'll have a CheckBox at the end of each row, I'm assuming this is what you want, right? – user Jul 30 '14 at 12:25
  • Yeah but I am getting failed to read row 0, column 2, from Cursor Windows which has 4 rows , 2 columns. Can you help me check my edited portion? –  Jul 30 '14 at 12:29
  • @20Cents In the for loop write: `for (int j = 0; j < cols + 1; j++) { if(j == cols) { .. add the CheckBox.. cb.setPadding(0, 5, 0, 5); row.addView(cb); break;} .. next add the rest of code with the TextView` . Right now, even for j = cols(there's no column for this integer) you still try to access it. – user Jul 30 '14 at 12:37
  • Sorry, once again, do you know how to add table header programmatically? –  Jul 30 '14 at 13:02
  • @20Cents A table header is nothing special than a simple row. So before that `do-while` block insert a row that will represent the header. Keep in mind that you add one extra column, with the CheckBoxes, so you need to match the number of columns in the do-while loop with the columns in that header row. – user Jul 30 '14 at 13:48
  • I did in this way: TableRow headerRow = new TableRow(this); headerRow.setLayoutParams(new LayoutParams( TableLayout.LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); headerRow.addView("ID"); But it tells me The method addView(View) in the type ViewGroup is not applicable for the arguments (String) –  Jul 30 '14 at 13:57
  • @20Cents addView() expects a View and not a simple String. Instead of "ID" you create a TextView, set its text to "ID" and then add the TextView to the header row. It's basically the same thing you've done below when you add the TextViews in the for loop, there's no special header row just an ordinary row to which you add your headers. – user Jul 30 '14 at 14:04
  • Can you help me check my edited portion? Because I am getting error message as the specified child already has a parent –  Jul 30 '14 at 14:10
  • @20Cents `...row.addView(tv4);table_layout.addView(row); do { int cols = mCur.getColumnCount(); row = new TableRow(this); row.setLayoutParams(new TableLayout.LayoutParams( TableLayout.LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));...` . If you have any more questions please start a new question, we have diverged from the initial question which is not ok. – user Jul 30 '14 at 14:22
  • Sorry but one last question, I modified my code as you suggested by adding 4 text view as the table header but my checkbox column is missing already. I only have 3 column of data and another one column is for the checkBox. Why is it so? –  Jul 30 '14 at 14:33
  • @20Cents Make sure you use the proper LayoutParams and also that the number of columns you add to the header are the same as the number of columns in the data part of the table. If this doesn't solve the problem post a new question showing you current buildTable() method that you have. – user Jul 30 '14 at 14:48