最近在做flutter web的开发,需要做一个类似云文档中表格固定顶部栏和左侧栏的需求,也就是冻结列表的功能
那么在pub上呢也有不少的开源库,比如:
table_sticky_headers

data_table_2

如果说只是简单的表格和吸顶,那么这两个库就完全可以满足需求,那么到这就不用往下看了
与NestedScrollView结合的吸顶效果实践
实则需求是这样的:希望左侧栏可以悬停的同时,顶部的表头也可以和NestedScrollView的一部分一起悬停在顶部
希望蓝色矩形的这一部分可以吸顶悬停

向上滑到顶的效果(蓝色矩形)

直接撸代码开始实践:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('NestedScrollView with '),
backgroundColor: Colors.amber,
),
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) => _buildHeadWidget(context),
body: StickyHeadersTable(
columnsLength: titleColumn.length,
rowsLength: titleRow.length,
columnsTitleBuilder: (i) => Text(titleColumn[i]),
rowsTitleBuilder: (i) => Text(titleRow[i]),
contentCellBuilder: (i, j) => Text(data[i][j]),
legendCell: Text('Sticky Legend'),
),
),
);
}
List<Widget> _buildHeadWidget(BuildContext context) {
return [
SliverToBoxAdapter(
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 100, horizontal: 30),
color: Colors.yellow,
child: Text(
"header",
style: TextStyle(fontSize: 65, fontWeight: FontWeight.bold),
),
),
),
SliverPersistentHeader(
pinned: true,
delegate: CommonSilverAppBarDelegate(
Container(
height: 100,
color: Colors.red,
alignment: Alignment.center,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.symmetric(vertical: 30),
child: Text(
"persistentHeader",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
)
// _buildHeadTabRowWidget()
],
),
),
),
),
];
}
实现的效果如下图:
数据很少的时候:
整体的效果不尽如人意,用户交互很差劲,主要有这么几个问题:
- 表格顶部没有跟随NestedScrollView一起吸顶(其实也是预期能想到的,表头并没有写到PersistentHeader里面)
- 滑动body部分的时候,header部分并没有往上滚动,没有那种粘在一起的效果,在滑动到列表最底部的时候,Header才往上一顿一顿的挪动,感觉一卡一卡的,很难受
- 在数据量很少的时候会明显的感觉到:向上滑动列表,body里顶部的内容会被吸顶的PersistentHeader遮挡
对于以上问题的解决方案
对于问题1
需要把源码中的头部拿出来,放到NestedScrollView的PersistenHeader里面,这一部分的代码需要提取出来,然后放入PersistenHeader当中
并且需要处理ScrollController联动的情况,需要声明一个该插件中的ScrollControllers对象,并且在build的时候拿到源码内的notification回调方法
对于问题2和3
通过SliverOverlapAbsorber + SliverOverlapInjector的组合可以一起解决
优化后的效果:

在数据量很少的时候:

项目地址
这是项目demo地址:https://github.com/pengboboer/sticky-headers-table
如果对你有帮助,动动小手给一个star,谢谢。