I'm trying to make a table/grid filled with items. So far, I have implemented a GridView as proposed by Fuzzical Logic. Here is an image of the result. I can scroll in both directions.
My problem is that by setting a new OnTouchListener to my GridView (which enables scrolling in both directions), my items are not clickable anymore. I have tried to call the OnItemClickListener from the method onTouch of my GridView, but I think it's too much complicated.
So I am asking you now, what is the best approach to show a table of clickable items scrollable in both directions.
Also, the number of items can vary a lot, the number of columns as well. There can be "empty" cells.
I really like the GridView, because it's easy to manage, but it lacks the 2D scroll. Any idea ?
Gordak
I have implemented a clickable Table the following way:
TableLayout table = (TableLayout) findViewById(R.id.tableReportsList);
table.setStretchAllColumns(true);
table.setShrinkAllColumns(true);
final String tag = "tag";
for (Report tempReport : reportsRepository)
{
TableRow row = new TableRow(this);
TableLayout.LayoutParams tableRowParams=new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT,TableLayout.LayoutParams.WRAP_CONTENT);
tableRowParams.setMargins(0, 10, 0, 10);
row.setLayoutParams(tableRowParams);
row.setClickable(true);
TextView tvName = new TextView(this);
tvName.setBackgroundDrawable(getResources().getDrawable(R.drawable.table_row_shape));
tvName.setText(tempReport.getName());
tvName.setGravity(Gravity.CENTER_HORIZONTAL);
tvName.setTextColor(getResources().getColor(R.color.my_black));
tvName.setTag(tag);
row.addView(tvName);
TextView tvPath = new TextView(this);
tvPath.setBackgroundDrawable(getResources().getDrawable(R.drawable.table_row_shape));
tvPath.setText(tempReport.getPath());
tvPath.setGravity(Gravity.CENTER_HORIZONTAL);
tvPath.setTextColor(getResources().getColor(R.color.my_black));
row.addView(tvPath);
map.put(tempReport.getName(), tempReport);
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
TextView tvName = (TextView) v.findViewWithTag(tag);
Log.d(TAG, "looking for report with name: " + tvName.getText());
Report report = (Report)map.get(tvName.getText());
Log.d(TAG, "The report found: " + report.toString());
Map<String, String> valuesmap = new HashMap<String, String>();
valuesmap.put(GetParametersAsyncTask.REPORTID_PARAM, report.getId());
Log.d(TAG, "passed the following id to the asynctask: "+ report.getId());
GetParametersAsyncTask asyncTask = new GetParametersAsyncTask(ReportsTableActivity.this, ((SGRaportManagerAppObj)getApplication()).getCurrentUrl());
asyncTask.execute(valuesmap);
}
});
table.addView(row);
}
while the xml file looks like this:
<FrameLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="55dp" >
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tableReportsList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:shrinkColumns="*"
android:stretchColumns="*" >
<TableRow
android:layout_height="wrap_content"
android:background="#color/light_gray"
android:textStyle="bold" >
<TextView
android:id="#+id/nameLabel"
android:layout_height="wrap_content"
android:background="#drawable/table_row_shape"
android:gravity="center_horizontal"
android:text="#string/report_name"
android:textColor="#color/my_black"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:textStyle="bold" />
<TextView
android:id="#+id/pathLabel"
android:layout_height="wrap_content"
android:background="#drawable/table_row_shape"
android:gravity="center_horizontal"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:text="#string/report_path"
android:textColor="#color/my_black"
android:textStyle="bold" />
</TableRow>
</TableLayout>
</ScrollView>
see if you find it helpful.
Related
Here is a cut-down version of the table layout im using. I'm trying to simulate a HTML percentage width by using a weightSum of 100 on the table and applying layout_weight on each view appropriately.
From my C# code I'm then looking to add each line item dynamically as new TableRow to the table layout. I can't seem to figure out how to ensure that the columns line up in the new rows. This is different to HTML, where columns are always the same width per row.
I've been messing around LayoutParameters to try and set a weight, but doesn't seem possible on a textview.
<?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="wrap_content"
style="#style/pagetemplate">
<TableLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:minWidth="25px"
android:minHeight="25px"
android:weightSum="100"
android:id="#+id/idBasketTable"
style="#style/pagetemplate">
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="10"
android:text="Options"
android:visibility="invisible" />
<TextView
android:text="Product Name"
style="#style/textViewHeader"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_weight="30"
android:layout_height="wrap_content" />
<TextView
android:text="Qty"
style="#style/textViewHeader"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_weight="30"
android:layout_height="wrap_content" />
<TextView
android:text="Price"
style="#style/textViewHeader"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_weight="30"
android:layout_height="wrap_content" />
</TableRow>
</TableLayout>
<include
layout="#layout/Menu"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
</RelativeLayout>
Then from my code I'm attempting something similar to this (cut down for simplicity). You'll notice my attempted LayoutParameter code commented out on each View as this was making them disappear all together from the layout. Not sure whether I should be concentrating on the layout styles of the row itself or the individual views?
Secondly, in the first row, I've tried to create a column that has no title. The line item rows will include a small delete button here, which is why I've tried to make an empty column. Is there a better way to do this rather than creating a textView (used for nothing) and setting to invisible?
TableLayout tl = (TableLayout)FindViewById(Resource.Id.idBasketTable);
TableRow tr = new TableRow(this)
{
LayoutParameters = new TableRow.LayoutParams(TableRow.LayoutParams.MatchParent, TableRow.LayoutParams.MatchParent, 100)
};
TextView tv_ProductName = new TextView(this)
{
Text = item.ItemName//,
// LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent,ViewGroup.LayoutParams.WrapContent)
};
tv_ProductName.SetTextAppearance(this, Resource.Style.textViewDetail);
TextView tv_Qty = new TextView(this)
{
Text = item.ItemQty.ToString()//,
// LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent)
};
tv_Qty.SetTextAppearance(this, Resource.Style.textViewDetail);
TextView tv_Price = new TextView(this)
{
Text = item.ItemPrice.ToString()//,
// LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent)
};
tv_Price.SetTextAppearance(this, Resource.Style.textViewDetail);
ImageButton ib_Delete = new ImageButton(this)
{
// LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent,ViewGroup.LayoutParams.WrapContent)
};
//set the view values for the current row.
ib_Delete.SetImageResource(Resource.Drawable.deleteitem);
Guid itemID = item.ItemID;
//assign the delete onclick event.
ib_Delete.Click += delegate
{
deleteItem_OnClick(ib_Delete, itemID);
};
//add views to the row.
tr.AddView(ib_Delete);
tr.AddView(tv_ProductName);
tr.AddView(tv_Qty);
tr.AddView(tv_Price);
//add the row to the table layout.
tl.AddView(tr);
Hope this all makes sense, appreciate the feedback :)
I have a XML file containing TableLayout as follows:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp" >
<TableLayout
android:id="#+id/resulttable"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="3" >
<TableRow
android:id="#+id/tr"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_discription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="#+id/tv_left_vehicle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="#+id/tv_right_vehicle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</TableRow>
</TableLayout>
</ScrollView>
In the above table I want to show array list of string, for this I have done following code:
TableLayout table = (TableLayout) findViewById(R.id.resulttable);
for(int i=0;i<DArray.size();i++)
{
TableRow row = (TableRow)findViewById(R.id.tr);
String discription = DArray.get(i);
String leftVehicle = LArray.get(i);
String rightVehicle = RArray.get(i);
TextView tvD = (TextView)findViewById(R.id.tv_discription);
tvD.setText(discription);
TextView tvlPrice = (TextView)findViewById(R.id.tv_left_vehicle);
tvlPrice.setText(leftVehicle);
TextView tvrPrice = (TextView)findViewById(R.id.tv_right_vehicle);
tvrPrice.setText(rightVehicle);
row.addView(tvD);
row.addView(tvlPrice);
row.addView(tvrPrice);
table.addView(row);
}
but this code is arising exception. Here is LogCat error for my code.
E/AndroidRuntime(1897): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
I am beginner for this situation please help me find out the problem.
i think you should Try this way
TableLayout table = (TableLayout) findViewById(R.id.resulttable);
TableRow row = (TableRow)findViewById(R.id.tr);
TextView tvD = (TextView)findViewById(R.id.tv_discription);
TextView tvlPrice = (TextView)findViewById(R.id.tv_left_vehicle);
TextView tvrPrice = (TextView)findViewById(R.id.tv_right_vehicle);
for(int i=0;i<DArray.size();i++)
{
String discription = DArray.get(i);
String leftVehicle = LArray.get(i);
String rightVehicle = RArray.get(i);
tvD.setText(discription);
tvlPrice.setText(leftVehicle);
tvrPrice.setText(rightVehicle);
row.addView(tvD);
row.addView(tvlPrice);
row.addView(tvrPrice);
table.addView(row,id);
}
Provide id for row positioning
The thing is that you added in the xml the row and then you add it again and again in the loop.
If you want to have a TableLayout and add rows on it dinamicaly then you might want to create the row with its content in another xml file and inflate that xml in the for loop and then add the row to the table.
So, lets say you have the following inside another xml called row.xml:
<TableRow
android:id="#+id/tr"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_discription"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="#+id/tv_left_vehicle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<TextView
android:id="#+id/tv_right_vehicle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</TableRow>
And the TableLayout in another one (xml file):
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp" >
<TableLayout
android:id="#+id/resulttable"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="3" >
</TableLayout>
</ScrollView>
Then you would have this in the code:
TableLayout table = (TableLayout) findViewById(R.id.resulttable);
for(int i=0; i < DArray.size(); i++){
//get the row from the xml and add it on the table at each loop step
TableRow row = getActivity().getLayoutInflater() .inflate(R.layout.row, table, true);
String discription = DArray.get(i);
String leftVehicle = LArray.get(i);
String rightVehicle = RArray.get(i);
// get the labels from the row and populate themm with data, note that you don't have to add them again as they are allready added..
TextView tvD = (TextView)row.findViewById(R.id.tv_discription);
tvD.setText(discription);
TextView tvlPrice = (TextView)row.findViewById(R.id.tv_left_vehicle);
tvlPrice.setText(leftVehicle);
TextView tvrPrice = (TextView)row.findViewById(R.id.tv_right_vehicle);
tvrPrice.setText(rightVehicle);
}
You might have to tweak the code above a bit as I wrote it from my mind and didn't tested it but that should be the trick.
Why Cant you use listview and custom adapters for this implementation?. which will make your life easier.
Okay the second potential problem is also: table.addView(row);
rowgets added every single loop iteration but it's the same view. You can only add a view once to the hierarchy. You probably want a new instance for each loop iteration. I can't say for sure but this is likely the problem. or try to add with index position in viewgroup like
table.addView(row, index);
I have a table layout after some view in my xml file. Below is the code.
<ScrollView>
<LinearLayout>
..................................
.....................................
<Button
android:id="#+id/fetchbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="show details"
android:layout_margin="6dip"
android:layout_gravity="center_horizontal"
android:onClick="buttonOnClick"/>
<TableLayout
android:id="#+id/mytable_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical"
>
</TableLayout>
</LinearLayout>
</ScrollView>
Below is the code to add the rows programatically for a table layout:
public void buttonOnClick(View view)
{
showData();
}
public void showData()
{
List<DataSource> data = dbHelper.getData(selectedoption);
TableLayout tl = (TableLayout)findViewById(R.id.mytable_layout);
for(DataClass dataclass:data)
{
TableRow tr = new TableRow(ViewScreen.this);
TableRow.LayoutParams params = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT);
tr.setLayoutParams(params);
TextView labelTV = new TextView(ViewScreen.this);
labelTV.setText(dataclass.getColumnName());
labelTV.setTextColor(Color.RED);
TableRow.LayoutParams paramsTV1 = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT);
labelTV.setLayoutParams(paramsTV1);
tr.addView(labelTV);
// Creating a TextView to house the value of the after-tax income
TextView valueTV = new TextView(ViewScreen.this);
valueTV.setText(dataclass.getColumnValue());
valueTV.setTextColor(Color.BLACK);
TableRow.LayoutParams paramsTV2 = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT);
valueTV.setLayoutParams(paramsTV2);
tr.addView(valueTV);
// Adding the TableRow to the TableLayout
tl.addView(tr, new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}
}
So as per the above code, it's working fine. But the table row is always with one line. The table row height is not increased according to the content. Instead the part of text goes off screen and invisible. Can some one please help to solve this issue?
Picture:
create a custom single_row.xml as below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayoutSingleRowRecordsDetailedView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff" >
<TextView
android:id="#+id/textViewSingleRowRecordsDetailedViewCategoryField"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dp"
android:text="TextView"
android:textColor="#04B4AE"
android:textSize="15dp"
android:typeface="sans" />
<TextView
android:id="#+id/textViewSingleRowRecordsDetailedViewCategoryFieldValue"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:text="TextView"
android:textColor="#000000"
android:textSize="15dp"
android:typeface="sans" />
</RelativeLayout>
And then in my java code:
...
LayoutInflater inflate = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View view = inflate.inflate(R.layout.single_row_records_detailed_view, null);
TextView tv_field_name = (TextView) view.findViewById(R.id.textViewSingleRowRecordsDetailedViewCategoryField);
TextView tv_field_value = (TextView) view.findViewById(R.id.textViewSingleRowRecordsDetailedViewCategoryFieldValue);
if(al_field_value.get(i).equals(""))
{
null_count = null_count + 1;
continue;
}
else
{
tv_field_name.setText(get_field_name(al_cat_field_id.get(i)));
tv_field_value.setText(al_field_value.get(i));
}
linearLayout_details.addView(view);
...
Try making your Textview multiline.
add below lines to your code to make textview multiline.
yourtextview.setSingleLine(false);
hope this helps
set the following to your tablelayout:-
tablename.setColumnShrinkable(ColumnIndex, true);
you can set the shrinkable attribute of the tablelayout to get the effect you want. the document from Android developer website :
The width of a column is defined by the row with the widest cell in
that column. However, a TableLayout can specify certain columns as
shrinkable or stretchable by calling setColumnShrinkable() or
setColumnStretchable(). If marked as shrinkable, the column width can
be shrunk to fit the table into its parent object. If marked as
stretchable, it can expand in width to fit any extra space. The total
width of the table is defined by its parent container. It is important
to remember that a column can be both shrinkable and stretchable. In
such a situation, the column will change its size to always use up the
available space, but never more. Finally, you can hide a column by
calling setColumnCollapsed().
example :
<TableLayout
android:id="#+id/fragment_print_job_detail_info_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:layout_margin="#dimen/image_button_margin"
android:background="#drawable/round_corner_white_background_shape" >
Here is my xml:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/test"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" >
<TableRow
android:id="#+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
>
<TextView
android:id="#+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<TextView
android:id="#+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
</TableRow>
I generate the rest dynamically.
Right now it centers it horizontally on the screen but everything is on the left side. I know its a simple fix but I can't seem to get it right.
Here is my manual code:
for(Item l : leaders)
{
// Make a new row
TableRow row = new TableRow(this);
row.setBackgroundColor(Color.DKGRAY);
TextView name= new TextView(this);
TextView score = new TextView(this);
createView(row, name, l.getName());
createView(row, score, String.valueOf(l.getScore()));
name.setTextColor(Color.MAGENTA); // Just to distinguish between the columns
// Add row to table layout
tl.addView(row);
}
}
private void createView(TableRow row, TextView textView, String string)
{
textView.setText(string);
textView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
textView.setTextColor(Color.CYAN);
textView.setTextSize(32);
textView.setPadding(20, 0, 0, 0);
row.setPadding(0, 1, 0, 1);
row.addView(textView);
}
Also, the given answers didn't change the layout.
If anybody has the same problem, the trick is to set
android:stretchColumns="0"
in the TableLayout and
android:layout_gravity="center"
android:layout_width="match_parent"
within the content views inside the rows.
I think u should write android:layout_gravity="center" in table layout instead of android:gravity="center".
and you can ad the layoutGravity Centre for Table Layout set in center in parrent Layouts
as
android:layout_gravity="center"
you can set the Gravity Centre
myTableLayout.setGravity(Gravity.CENTER);
I have a TableLayout inside a ScrollView, that is I have a scrollable TableLayout! It is populated dynamically when I create Dialog's in different places of an Activity.
Actually everything works fine, but the fact that for every case there's a different header (with a title for each column) on that table and it scrolls along with the rows. As the content of that table is dynamic, the amount (as well as the width) of columns is unknown.
So, basically, that's my problem. I don't see point in posting code, as I need mostly a suggestion/workaround, but if that would help overcome the issue, let me know. Would appreciate some samples very much.
Here is a way :
http://sdroid.blogspot.com/2011/01/fixed-header-in-tablelayout.html
Note that there is a way to have this work every time : what you have to do is create a similar dummy row in the header, and set the texts in both dummies to the longest string you can find in the row (in number of chars, or, even better, do the comparison with Paint.getTextWidths)
package com.test.test;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class TestProjectTestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TableLayout tl_head1 = (TableLayout)findViewById(R.id.tl_head);
TableLayout tl_child1 = (TableLayout)findViewById(R.id.tl_child);
String headcol1="";
TableRow tr[]= new TableRow[40];
TextView tv[] = new TextView[1000];
for(int i=0; i <=30; i++)
{
tr[i]=new TableRow(this);
for(int j=1; j<=5; j++)
{
tv[j]=new TextView(this);
tv[j].setId(j);
tv[j].setText("testingmultiple data hello"+""+j);
tv[j].setTextColor(Color.WHITE);
if(headcol1.length() < tv[j].getText().length())
{
headcol1=null;
headcol1=tv[j].getText().toString();
}
tr[i].addView(tv[j]);
}
tl_child1.addView(tr[i]);
}
TableRow trhead= new TableRow(this);
TextView tvhead[] = new TextView[5];
for(int i=0;i<=4;i++)
{
tvhead[i] = new TextView(this);
tvhead[i].setTextColor(Color.WHITE);
tvhead[i].setHeight(0);
tvhead[i].setText(headcol1);
trhead.addView(tvhead[i]);
}
tl_head1.addView(trhead);
}
}
<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/hsv_main"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="#+id/ll_main"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TableLayout
android:id="#+id/tl_head"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TableRow
android:id="#+id/tr_head"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/tv_hidden1"
android:layout_gravity="center_horizontal"
android:text="12"
android:textColor="#FFFFFF"
/>
<TextView
android:id="#+id/tv_hidden2"
android:layout_gravity="center_horizontal"
android:text="123"
android:textColor="#FFFFFF"
/>
<TextView
android:id="#+id/tv_hidden3"
android:layout_gravity="center_horizontal"
android:text="1234"
android:textColor="#FFFFFF"
/>
<TextView
android:id="#+id/tv_hidden4"
android:layout_gravity="center_horizontal"
android:text="12345"
android:textColor="#FFFFFF"
/>
<TextView
android:id="#+id/tv_hidden5"
android:layout_gravity="center_horizontal"
android:text="123456"
android:textColor="#FFFFFF"
/>
</TableRow>
</TableLayout>
<ScrollView
android:id="#+id/sv_child"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TableLayout
android:id="#+id/tl_child"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</TableLayout>
</ScrollView>
</LinearLayout>
</HorizontalScrollView>
Android scrollable TableLayout with a dynamic fixed header is very simple. Follow this steps
Step 1:
Create a TableLayout and use android:layout_alignParentTop="true" this will keep this layout always in top.
Step 2:
With in ScrollView create another TableLayout for contents with out Rows (For Dynamic content).
Step 3:
Add Rows and columns dynamically. While adding each column (TextView) assign the width to an temporary variable.
Ex
tvContentText.measure(0, 0);
tempmaxwidth=tvContentText.getMeasuredWidth();
Step 4:
Check for max width and assign max width to main variable.
Ex:
if (tempmaxwidth > maxwidth)
maxwidth=tempmaxwidth;
Step 5:
After assigning content details. Assign the max width of each column to its header column.
Ex:
TextView tvh1 = (TextView) findViewById(R.id.h1);
tvh1.setWidth(maxwidth);
The xml and code is below
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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=".MainActivity">
<TableLayout
android:id="#+id/headertbl"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:background="#color/colorPrimary"
android:layout_height="wrap_content"
android:stretchColumns="*">
<TableRow>
<TextView
android:id="#+id/h1"
android:layout_height="wrap_content"
android:text="H1"
android:textStyle="bold"
android:textAlignment="center"
android:textSize="20sp" />
<TextView
android:id="#+id/h2"
android:layout_height="wrap_content"
android:text="H2"
android:textStyle="bold"
android:textAlignment="center"
android:textSize="20sp" />
<TextView
android:id="#+id/h3"
android:layout_height="wrap_content"
android:text="H3"
android:textStyle="bold"
android:textAlignment="center"
android:textSize="20sp" />
<TextView
android:id="#+id/h4"
android:layout_height="wrap_content"
android:text="H4"
android:textStyle="bold"
android:textAlignment="center"
android:textSize="20sp" />
</TableRow>
</TableLayout>
<ScrollView
android:layout_below="#id/headertbl"
android:id="#+id/container"
android:layout_marginTop="10dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical">
<TableLayout
android:id="#+id/contenttbl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stretchColumns="*">
</TableLayout>
</ScrollView>
</RelativeLayout>
MainActivity.xml
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TableLayout tl = (TableLayout) findViewById(R.id.contenttbl);
int tempmaxwidth=0,maxwidth=0;
int tempmaxwidth1=0,maxwidth1=0;
int tempmaxwidth2=0,maxwidth2=0;
int tempmaxwidth3=0,maxwidth3=0;
for(int i=0;i<50;i++)
{
TableRow newRow = new TableRow(getApplicationContext());
newRow.setId(i);
TextView tvContentText = new TextView(getApplicationContext());
if(i!=6)
tvContentText.setText("Content 1");
else
tvContentText.setText("---- Content with Max width");
tvContentText.setTextColor(Color.BLACK);
tvContentText.setTextSize(16f);
tvContentText.measure(0, 0);
tempmaxwidth=tvContentText.getMeasuredWidth();
if (tempmaxwidth>maxwidth)
maxwidth=tempmaxwidth;
TextView tvContentText1 = new TextView(getApplicationContext());
//tvContentText1.setText(Integer.toString(maxwidth));
tvContentText1.setText("Content 2");
tvContentText1.setTextColor(Color.BLACK);
tvContentText1.setTextSize(16f);
tvContentText1.measure(0, 0);
tempmaxwidth1=tvContentText1.getMeasuredWidth();
if (tempmaxwidth1>maxwidth1)
maxwidth1=tempmaxwidth1;
TextView tvContentText2 = new TextView(getApplicationContext());
tvContentText2.setText("Content 3");
tvContentText2.setTextColor(Color.BLACK);
tvContentText2.setTextSize(16f);
tvContentText2.measure(0, 0);
tempmaxwidth2=tvContentText2.getMeasuredWidth();
if (tempmaxwidth2>maxwidth2)
maxwidth2=tempmaxwidth2;
TextView tvContentText3 = new TextView(getApplicationContext());
tvContentText3.setText("Content 4");
tvContentText3.setTextColor(Color.BLACK);
tvContentText3.setTextSize(16f);
tvContentText3.measure(0, 0);
tempmaxwidth3=tvContentText3.getMeasuredWidth();
if (tempmaxwidth3>maxwidth3)
maxwidth3=tempmaxwidth3;
newRow.addView(tvContentText);
newRow.addView(tvContentText1);
newRow.addView(tvContentText2);
newRow.addView(tvContentText3);
tl.addView(newRow);
}
// Assigning Max width to header column
TextView tvh1 = (TextView) findViewById(R.id.h1);
tvh1.setWidth(maxwidth);
TextView tvh2 = (TextView) findViewById(R.id.h2);
tvh2.setWidth(maxwidth1);
TextView tvh3= (TextView) findViewById(R.id.h3);
tvh3.setWidth(maxwidth2);
TextView tvh4= (TextView) findViewById(R.id.h4);
tvh4.setWidth(maxwidth3);
}
Well for me I didn't want to go through the trouble of worrying about alignment of columns so I created this first of all:
public static Boolean SET_TABLE_HEADER;
Then I created this function to set my TableHeader:
public void setTableHeader(TableLayout tbl) {
TableRow tr = new TableRow(context);
TextView tcView = new TextView(context);
tcView.setText("Class");
tcView.setTextColor(Color.BLACK);
tcView.setAllCaps(true);
tcView.setTypeface(null, Typeface.BOLD);
tcView.setGravity(Gravity.CENTER_HORIZONTAL);
tr.addView(tcView);
TextView tfView = new TextView(context);
tfView.setText("Fee");
tfView.setTextColor(Color.BLACK);
tfView.setAllCaps(true);
tfView.setTypeface(null, Typeface.BOLD);
tfView.setGravity(Gravity.CENTER_HORIZONTAL);
tr.addView(tfView);
TextView tqView = new TextView(context);
tqView.setText("Available");
tqView.setTextColor(Color.BLACK);
tqView.setAllCaps(true);
tqView.setTypeface(null, Typeface.BOLD);
tqView.setGravity(Gravity.CENTER_HORIZONTAL);
tr.addView(tqView);
// Adding row to Table
tbl.addView(tr);
// Table Header Has Been Set
SET_TABLE_HEADER = false;
}
Then inside my loop:
if (SET_TABLE_HEADER) {
setTableHeader(tbl);
}
Where tbl is the instance of my TableLayout in my view. This works for me.
Of course you will have to initialize SET_TABLE_HEADER to true at the point where you start creating your table.