BVtp BVtp - 2 months ago 7
Android Question

Crash trying to add views to a Table dynamically (Android)

I want to implement something like this(RTL) :

enter image description here

In other words, being able to add views to a layout in 3 columns.
I tried doing this:

my_fragment.xml:

...
<TableLayout
android:id="@+id/myTable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:numColumns="3"
android:stretchColumns="*"
android:layout_margin="10dp"
android:background="@color/background_color">
</TableLayout >
...


myFragment.java:

TableRow[] tableRows = new TableRow[ serverResponse.getData().size()/3 ];
for( int i=0, j=0; i<serverResponse.getData().size() ;i++ )
{
View customView = inflater.inflate(R.layout.data_item, tableRows[j], true);
((TextView) customView.findViewById(R.id.viewText)).setText(serverResponse.getData().get(i).getItemData());
if( i%3 == 0 ) {
j++;
}

myTable.addView( tableRows[i] , new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT) );
}


Crash :
Cannot add a null child view to a ViewGroup


EDIT :
thanks to Mike M.'s solution it now works. However, one column is always cut :
enter image description here

The data_item.xml is simple :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right">

<TextView
android:id="@+id/viewText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:ellipsize="end"/>

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:background="@drawable/circle"/>

</LinearLayout>

Answer

You're getting that error because you're not initializing the individual elements of your TableRow array. Initializing the array itself does not initialize the elements. That is, you need to instantiate a new TableRow for each array index.

Also, you'll need to add the cells to each TableRow with the addView() method, rather than inflating them into it, or each new cell with occupy the whole row.

final int size = serverResponse.getData().size();
final int numCols = 3;
final int numRows = size / numCols + (size % numCols == 0 ? 0 : 1);
final TableRow[] tableRows = new TableRow[numRows];

final TableLayout.LayoutParams tableParams =
    new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,
                                 TableLayout.LayoutParams.WRAP_CONTENT);
final TableRow.LayoutParams rowParams =
    new TableRow.LayoutParams(0,
                              TableRow.LayoutParams.WRAP_CONTENT,
                              1);

for (int i = 0; i < numRows; i++) {
    tableRows[i] = new TableRow(getContext());
    for (int j = 0; j < numCols; j++) {
        final int index = i * numCols + j;
        final View customView = inflater.inflate(R.layout.data_item,
                                                 tableRows[i], false);
        if (index < size) {
            ((TextView) customView.findViewById(R.id.noteText))
                .setText(serverResponse.getData().get(index).getItemData());
        }
        else {
            ((ImageView) customView.findViewById(R.id.circle))
                .setVisibility(View.INVISIBLE);
        }
        tableRows[i].addView(customView, rowParams);
    }
    myTable.addView(tableRows[i], tableParams);
}

In the data_item layout, set an ID of circle on the ImageView.