需要解决IndexedStack始终与最大子项一样大的问题。

11
我有一个索引栈。第一个子小部件具有相对于第二个子小部件一半的内容,但是第一个子小部件的高度与第二个子小部件相同。由于设计原因,这似乎是预期的结果,但很烦人,因为当我在第一个子小部件上滚动时,底部会多出一堆空白。我该如何解决这个问题?
Flutter团队为什么要这样设计呢?为什么不按照小部件的实际高度赋予小部件子项高度,而是按照最大子项的高度呢?
5个回答

8

这个解决方案保留了状态,这是IndexedStack的一个关键特性。大多数已发布的解决方案在索引更改时丢弃状态,而我需要保留状态。

如果处于活动状态,则Widget高度没有限制,并且如果处于非活动状态,则受到1像素SizedBox的约束。这使得活动的Widget最大化,因此您的Widget以其个人大小呈现,而不会添加空间。

IndexedStack(
  index: selectedIndex,
  children: [
    SizedBox(
        height: selectedIndex == 0 ? null : 1,
        child: Widget1()),
    SizedBox(
        height: selectedIndex == 1 ? null : 1,
        child: Widget2()),
    SizedBox(
        height: selectedIndex == 2 ? null : 1,
        child: Widget3())
  ],
);

4
您可以在IndexedStack中使用visibility。像这样:
IndexedStack(
  index: selectedIndex,
  children: [
    Visibility(
     visible: selectedIndex == 0,
     child: Container(
       height: 300,
     ),
    Visibility(
      visible: selectedIndex == 1,
      child: Container(
      height: 100,
    )
  ]
)

你也可以在列中实现这一点,只需用列替换indexedstack即可。

1
如果您不需要保留子小部件的状态,那么这非常有效。如果您需要IndexedStack的状态保留功能,请选择另一个选项。 - Dylan Cross

1
我今天遇到了完全相同的问题。 我的解决方法是仅呈现基于索引号可见的堆栈。
      Widget _buildPage2() {
        if(index != 1) { // Empty container
          return Container();
        }
        return Column( // Actual Widget which has a different height
          children: <Widget>[]
        );
     }

我仍然没有弄清楚如何让controller.animateTo起作用。

编辑

我通过触发Future.delayed事件使controller.animateTo工作。 更好的方法是使用WidgetBindings,如其他帖子中所解释的。


谢谢!这终于帮助我解决了我的方法。 - Andres Naranjo

0

我遇到了同样的问题,并找到了这个解决方法。

class CustomIndexedStack extends StatelessWidget {
  const CustomIndexedStack(
      {super.key, required this.index, required this.children});

  final List<Widget> children;
  final int index;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: children
          .mapIndexed(
              (widget, i) => Offstage(offstage: index != i, child: widget))
          .toList(),
    );
  }
}

extension IndexedIterable<E> on Iterable<E> {
  Iterable<T> mapIndexed<T>(T Function(E e, int i) f) {
    var i = 0;
    return map((e) => f(e, i++));
  }
}

1
请为代码添加一些注释,以解释其功能。 - Akbar Masterpadi

0
Co ask. 当我将索引堆栈作为自定义滚动视图中的一个sliver之一时,我遇到了这个问题。子元素是可滚动列表。因此,当索引堆栈的一个子元素的列表比另一个子元素的列表多时,底部会有额外的白色空间。

这不是一个答案 - undefined

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