我设法通过在
Scrollable.ensureVisible
中设置
alignmentPolicy
属性来解决这个问题,该属性基于当前选定的
ListView
项目的索引和新选择的
ListView
项目的索引。如果新选择的项目的索引大于当前选定项目的索引,则将
alignmentPolicy
设置为
ScrollPositionAlignmentPolicy.keepVisibleAtEnd
,否则将其设置为
ScrollPositionAlignmentPolicy.keepVisibleAtStart
。此外,
itemBuilder
必须使用一个新的
GlobalKey
创建每个项目,如下面的代码所示,这允许从每个单独的
ListView
项目中获取上下文。
请注意,对于我的解决方案,我使用了ListView.builder
。
[注意]
唯一的问题是,如果您选择的项目的索引低于当前选定的项目,但新选择的项目需要向右滚动才能看到它,那么它将不会滚动以使其可见,反之亦然。
例如,如果当前选定的索引是5,新选择的索引是3,并且ListView需要向右滚动以使项目可见,则不会发生滚动。
然而,如果当前选定的索引是5,新选择的索引是3,并且ListView需要向左滚动以使项目可见,则会发生滚动。
示例:
Example
List<Widget> tabs = [YourTabWidget(), YourTabWidget(), YourTabWidget()];
int activeTabIndex = 0;
@override
Widget build(BuildContext context) {
return ListView(
children: [
ListView.builder(
itemCount: tabs.length,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
GlobalKey dataKey = GlobalKey();
return GestureDetector(
key: dataKey,
onTap: () {
Scrollable.ensureVisible(
dataKey.currentContext!,
alignmentPolicy: index > activeTabIndex
? ScrollPositionAlignmentPolicy.keepVisibleAtEnd
: ScrollPositionAlignmentPolicy.keepVisibleAtStart,
);
setState(
() {
activeTabIndex = index;
},
);
},
child: tabs[index],
);
},
),
],
);
}
编辑:通过两次调用Scrollable.ensureVisible
解决了之前提到的问题,一次使用alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd
,然后立即再次调用它,并使用alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtStart
。
所以不再是:
onTap: () {
Scrollable.ensureVisible(
dataKey.currentContext!,
alignmentPolicy: index > activeTabIndex
? ScrollPositionAlignmentPolicy.keepVisibleAtEnd
: ScrollPositionAlignmentPolicy.keepVisibleAtStart,
);
setState(
() {
activeTabIndex = index;
},
);
},
它将是:
onTap: () {
Scrollable.ensureVisible(
dataKey.currentContext!,
alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd
);
Scrollable.ensureVisible(
dataKey.currentContext!,
alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtStart
);
setState(
() {
activeTabIndex = index;
},
);
},