在Flutter中的垂直列表视图内滚动到水平列表视图中的某个项目

3

我内部有一个选项卡栏,使用水平的ListView实现,页面整体内容在垂直滚动视图(vertical scroll view)中。当点击“第三个选项卡”时,需要滚动以显示完整名称。问题在于ListView没有滚动到项目的方法。其他可能的解决方案:

  • Scrollable.ensureVisible(context) 几乎可以实现,但问题是它也会滚动垂直列表,这不是我想要的。而且我没有看到阻止这样做的方法。
  • 使用scrollable_positioned_list package,将滚动到应该在第一个位置的项目,从而导致iOS设备上出现巨大的过度滚动反弹。这种方法缺少类似于 ScrollPositionAlignmentPolicy.keepVisibleAtStart 的ensureVisible方法。
  • 项目的宽度不固定,因此排除了几种解决方案。

enter image description here


这里情况一样……你找到解决办法了吗? - Geraldo Neto
同样的问题。目前,我只能进行更多的计算。 - Benjamin Sx
1个回答

0
我设法通过在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;
                },
              );
            },

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接