TableLayout布局的效果就是整齐的表格,看着非常舒心。当遇到数据较多时,可以添加到ScrollView和HorizontalScrollView进行上下和左右的滑动。左右滑动的体验性一般比较合理,但是上下滑动就有些不舒心了。因为常规中,第一行数据是表头,即所谓的列名,在上下滑动的时候标题列也随着滑动而隐藏掉。这就导致看下面的数据时不知道每列的数据指的是什么,体验性就比较差。理想的做法就是固定标题栏,只有数据可以上下滚动,这样,就可以一直看到标题栏了。遗憾的是Android并没有提供直接固定标题栏的方法,那么这就要我们程序猿自己想法实现了。当然,程序猿是一种非常聪明的生物,这群家伙大脑非常活跃,想出了不止一种实现的方法。而我作为其中一支猿,只想出了一种,其他方法还望猿们一块分享。
首先说下实现思路:和普通的加载数据一样,把数据完整的显示在TableLayout中,创建一个ScrollView,将TableLayout添加其中。这时,上下滚动的时候标题栏会滚动隐藏,这个TableLayout叫做数据Layout。然后再创建一个TableLayout,这个TableLayout只用于显示标题栏,这个叫做标题Layout。再创建一个FramLayout,把数据Layout和标题Layout按照顺序添加到FramLayout中。这时,整个显示并不会左右滑动,因此需要将FramLayout加入到一个HorizontalScrollView中。大概就是这样。
不过遇到一种情况时需要做下处理:当你的TableRow中每列数据的宽度是WRAP_CONTENT时,这个时候需要设置标题Layout中每个列的宽度与数据Layout中对应列的宽度相同。
下面贴下伪代码,不能运行、
ScrollView ssv=new ScrollView(this); //竖向滑动
HorizontalScrollView sv=new HorizontalScrollView(this);//横向滑动
FrameLayout frameLayout=new FrameLayout(this); //布局
Timer timer;
TimerTask timerTask;
loadData(){
TableLayout dataLayout= new TableLayout(this); //显示数据的TableLayout
TableRow dataHead=new TableRow(this); //显示标题的行
init(dataHead); //加载数据给标题
dataLayout.addView(dataHead);
//显示标题的TableLayout
TableLayout headLayout= new TableLayout(this);
//显示标题的行
TableRow newHead=new TableRow(this);
init(newHead); //加载数据给标题
ssv.addView(dataLayout); //使数据Layout能上下滑动
frameLayout.addView(ssv); //添加数据Layout到FrameLayout中
//覆盖数据Layout中的标题行,注意,headLayout没在ScrollView中,所以不会上下滑动
frameLayout.addView(headLayout);
//使整体能够左右滑动
sv.addView(frameLayout);
//加载数据到dataLayout中
.....//加载完成
//由于数据Layout每列的宽度是根据内容调节的,所以在数据Layout加载好后,等待那么一小会儿,给标题Layout设置宽度,与数据Layout宽度对齐
timer = new Timer();
startTimerTask();
}
init(TableRow row){
//加载列名到第一行
}
private void startTimerTask() {
if (timer != null) {
if (timerTask != null) {
timerTask.cancel();
}
}
timerTask = new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = 9;
handler1.sendMessage(message);
}
};
timer.schedule(timerTask, 300); //300毫秒后执行
}
Handler handler1 = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 9:
//遍历数据Layout标题行的子元素
for (int i = 0; i < dataHead.getChildCount(); i++) {
//获取数据Layout标题行中的子元素
Object o = dataHead.getChildAt(i);
//获取标题Layout中标题行的子元素
Object o2 = newHead.getChildAt(i);
if (o instanceof TextView) {
TextView tv = (TextView) o;
//获取数据Layout标题行中的子元素的宽度
int w = tv.getWidth();
//设置标题Layout中标题行子元素的宽度
((TextView) o2).setLayoutParams(new TableRow.LayoutParams(w, ViewGroup.LayoutParams.WRAP_CONTENT));
}
}
if (newHead.getParent() == null) {
headLayout.addView(newHead, new TableLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT
, ROW_HEIGHT));
}
if (timerTask != null) {
timerTask.cancel();
}
break;
}
}
};
大概思路就是上面所说,可能我叙述的比较不直观,没图没真相,但是如果你想实现这样的效果最好还是耐心看完。