我一直在使用ScrollController
来检测滚动进行过程中滚动位置的变化,即不是在滚动变化结束时,所以我可以使用点击测试来确定哪种自定义{{ 1}}位于特定位置,从而知道小部件列表的哪个索引位于视口的顶部。
我的小部件列表并非都相等,因此我认为某些使用尺寸的方法不合适。我一直在使用scroll_to_index滚动到索引,然后发现一个问题post出现了问题issue comment,该问题描述了使用MetaData小部件并通过点击测试来检测它们,所以这就是我试图做的。
首先输入代码...
MetaData
本质上,这仅呈现具有一些唯一Text的ListTiles列表。每个class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
ScrollController _scrollController;
@override
void initState() {
_scrollController = ScrollController();
_scrollController.addListener(() {
print("ScrollController listener fired");
// Test A
// ItemMetaData info = getMeta(0, 0);
// if (info != null) {
// print("ScrollController: Current tab index: ${info.index}");
// }
// Test B
Future.microtask(() {
ItemMetaData info = getMeta(0, 0);
if (info != null) {
print("ScrollController: Current tab index: ${info.index}");
}
});
});
super.initState();
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _buildList(context),
);
}
Widget _buildList(BuildContext context) {
return ListView.builder(
itemCount: 30,
controller: _scrollController,
itemBuilder: (context, index) => _getChild(index),
);
}
T getMeta<T>(double x,double y){
var renderBox = context.findRenderObject() as RenderBox;
var offset = renderBox.localToGlobal(Offset(x,y));
HitTestResult result = HitTestResult();
WidgetsBinding.instance.hitTest(result, offset);
for(var i in result.path){
if(i.target is RenderMetaData){
var d = i.target as RenderMetaData;
if(d.metaData is T) {
return d.metaData as T;
}
}
}
return null;
}
Widget _getChild(int index){
return MetaData(
metaData: ItemMetaData(index),
child: ListTile(
title: Text("Child:$index"),
),
);
}
}
class ItemMetaData {
final int index;
ItemMetaData(this.index);
}
都包装在ListTile
中,并通过自定义类提供了相同的索引值。
我使用附加到列表的MetaData
并添加了一个侦听器来检测列表更改。显然,随着列表的滚动,侦听器中的第一个print语句会得到很多输出,但是我想确定侦听器何时触发。
我在侦听器中尝试了2个不同的代码块,目的是在特定位置检测ScrollController
。 测试A 和测试B 代码块的区别仅在于后者将命中的测试代码包装在RenderMetaData
中-我是从上面的上一个Flutter注释链接获得的。
我正在使用稳定的Flutter SDK和Android模拟器进行滚动测试。
仅测试代码
我只看到第一个打印语句,而没有看到第二个“当前标签索引”语句,因此基本上找不到元数据。
仅测试B代码
当我执行滑动手势(例如滑动)时,我(几乎)始终看到第二个打印语句。如果我进行按住滚动操作,就像将手指放在屏幕上并以任意速度向上或向下移动(不放开),我仍然会看到第一个打印内容,但根本看不到第二个打印内容。
所以我的问题是为什么我不能以这种方式获得一致的元数据命中测试结果,而我缺少可以解决的结果吗?