Android scrollable TableLayout with a dynamic fixed header
I have a TableLayout
inside a ScrollView
, that is I have a scrollable TableLayo开发者_运维百科ut
! 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.
精彩评论