3

I am working on an Android project and I have an issue with the layout.

What I have is a JSONArray that I loop round inflating a new TableRow and within the loop round another array within the JSON array to populate it with fields. The fields are populated by inflating an XML file and adding this view to the table row. However, at the moment nothing shows up in the row.

Below is my TableRow XML file:

<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"/>

Below is my TextView XML:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:textColor="@color/black"
    android:padding="5dp"/>

Below is how I am populating the TableRow and the TextView:

for (int i = 0; i < result.length(); i++) {
    final TableRow tr = (TableRow) getLayoutInflater(getArguments()).inflate(R.layout.result_table_row_light_theme, resultTable, false);
    if (i == 0) {
        tr.setBackgroundColor(getResources().getColor(R.color.appPrimaryColour));
    } else if (i % 2 == 0) {
        if (settings.getInt(Defines.SharedPreferenceSettings.APPLICATION_THEME,
                com.BoardiesITSolutions.Library.R.style.LibAppTheme) == com.BoardiesITSolutions.Library.R.style.LibAppTheme) {
            tr.setBackgroundColor(getResources().getColor(R.color.resultRowLightThemeAlternateRow));
        }
    }
    JSONArray array = result.getJSONArray(i);
    for (int j = 0; j < array.length(); j++) {
        final TextView textView;
        textView = (TextView) getLayoutInflater(getArguments()).inflate(R.layout.result_textview, tr, false);
        textView.setText(array.getString(j));
        if (i == 0) {
            textView.setTypeface(null, Typeface.BOLD);
            textView.setGravity(Gravity.CENTER_HORIZONTAL);
        }
        getActivity().runOnUiThread(new Runnable() {

            @Override
            public void run() {
                tr.addView(textView);
            }
        });
    }
    getActivity().runOnUiThread(new Runnable() {

        @Override
        public void run() {
            resultTable.addView(tr);
        }
    });
}

If I change my TextView XML file so that the layout_width is wrap_parent instead of 0dp then everything is shown on the screen.

However, when the textview is 0dp and the layout_weight is 1 then nothing is displayed, however I would have expected each text view to be evenly distributed across the width of the screen to fill the space.

What I should probably mention, don't know if it makes a difference, is the TableView is within a HorizontalScrollView. The row should fit in the width of the screen, if the data is smaller than the screen, but if the row won't fit, then the view will be horizontally scrollable.

UPDATE 1

Below is the XML that hosts the TableLayout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <ScrollView 
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scrollbars="horizontal">
        <LinearLayout 
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:orientation="vertical">
            <HorizontalScrollView 
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
                <TableLayout android:id="@+id/resultTable"
                    android:stretchColumns="*"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content">
                </TableLayout>
            </HorizontalScrollView>
        </LinearLayout>
    </ScrollView>
</RelativeLayout>
halfer
  • 19,824
  • 17
  • 99
  • 186
Boardy
  • 35,417
  • 104
  • 256
  • 447
  • A with of 0dp on each text view means there is no width and therefore nothing is going to show up. – cyroxis Mar 02 '15 at 22:17
  • But normally if you have layout_weight it will fill the available space. As they will all have a weight of 1, then they should be evenly proportioned across the screen. That's the case when all the textviews are added together as part of the XML instead of programmatically created anyway – Boardy Mar 02 '15 at 22:19
  • Ahh correct, I missed that. What is the XML for your TableLayout? Make sure its width is not set to wrap_content because layout_weight only applies to extra space in the TableRow. – cyroxis Mar 02 '15 at 22:24
  • The TableLayout and the Horizontal Scroll View is set to fill_parent. I've added the XML for the TableLayout to my question in case it helps – Boardy Mar 02 '15 at 22:29
  • Calling match_parent in the scrolling direction does not work for the child of a scroll view. – cyroxis Mar 02 '15 at 22:41

3 Answers3

2

What I should probably mention, don't know if it makes a difference, is the TableView is within a HorizontalScrollView.

It is a logical error to tell a child view inside a scrolling container to match_parent or fill the available space in any way. A scrolling container, like ScrollView or HorizontalScrollView measures its one-and-only child view as UNSPECIFIED so that the child can grow beyond the parent bound in that one direction (and, thus, be scrollable).

The child of a scrolling container is not given what the "available space" would be for it to fill, and operations like layout weight have no effect if the parent's dimension is not well-defined.

The row should fit in the width of the screen, if the data is smaller than the screen, but if the row won't fit, then the view will be horizontally scrollable.

The functionality you are looking for is fillViewport (docs link), which tells the scrolling container to force the child to match it's size if the measured width (in the horizontal case) is less than the parent. Use this in place of applying a weight.

devunwired
  • 62,780
  • 12
  • 127
  • 139
  • Excellent thank you, I've been struggling with this for ages. Using the fillViewPort fixes it – Boardy Mar 05 '15 at 18:40
1

Try this :

public void createTextView(Context context, LinearLayout parent) {
    final TextView v = new TextView(context);
    parent.addView(v); // Mandatory!
    v.post(new Runnable() { // In UI Thread. View Must be added to parent before getting layout params!
        @Override
        public void run() {

             // Get params:
             LinearLayout.LayoutParams lParams = (LinearLayout.LayoutParams) v.getLayoutParams();

             // Set only target params:
             lParams.width = 0;
             lParams.weight = 1;
             v.setLayoutParams(lParams);
        }
    });
}
Sergey Shustikov
  • 15,377
  • 12
  • 67
  • 119
0

Can you try to do your layout in XML (just to debug it, with dummy data)? Does it work as expected?

The docs mention that:

children of a TableRow do not need to specify the layout_width and layout_height attributes in the XML file. TableRow always enforces those values to be respectively MATCH_PARENT and WRAP_CONTENT.

Not sure if that means that it'll also mess stuff up if you try to set these values. As you've found, it's clearly not just ignoring them if they are set.

The other part says that the parent of the TableRow should be a TableLayout - is that the type of resultTable (you mentioned TableView) - otherwise it will behave as a LinearLayout with horizontal orientation.

ataulm
  • 15,195
  • 7
  • 50
  • 92
  • It is in a table layout, I've included the XML to my question. I've done the test you suggested. If have the EditText have layout_width and layout_weight set, I get the same behaviour where nothing is displayed, if I omit those parameters from the EditTexts in the TableRow then it works – Boardy Mar 02 '15 at 22:37
  • **"It boils down to adding android:stretchColumns="1" to your TableLayout root and setting android:layout_width="0dp" to all the children in your TableRow's"** - see the comments on that answer too here: http://stackoverflow.com/questions/6647177/set-equal-width-of-columns-in-table-layout-in-android – ataulm Mar 02 '15 at 22:46
  • Even with all the children set to 0 width and the stretch columns set to 1, I still have the same issue – Boardy Mar 03 '15 at 15:45