Need a workaround for Indexedstack always being as big as the largest child

Viewed 962

I have an indexed stack. First child widget has half the content that the second child widget has, but the first child widget's height is the same as the second child widget. This seems to be the expected result due to the design but its annoying because when I scroll on the first child widget, there is a bunch of extra space at the bottom. How can I work around this?

Why did the Flutter team even design it like this? Why not give the widget children the height according the the widgets, not according to whatever the largest child is?

4 Answers

Co ask. I am experiencing this problem when I have the index stack as one of the slivers in a custom scroll view. The children are wash scrollable lists. So when one child of the indexed stack has more items in its list than the other, there is extra white space at the bottom

I faced the exact same issue today. My workaround is to only render the Stack which is visible based on the index number.

      Widget _buildPage2() {
        if(index != 1) { // Empty container
          return Container();
        }
        return Column( // Actual Widget which has a different height
          children: <Widget>[]
        );
     }

I still have not figured out how to get controller.animateTo working.

Edit

I got controller.animateTo to work by triggering a Future.delayed event. As a better approach you could use WidgetBindings, as explained in this other post.

I faced the same issue and found this workaround.

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++));
  }
}

you can use visibility inside a IndexedStack. Like this:

IndexedStack(
  index: selectedIndex,
  children: [
    Visibility(
     visible: selectedIndex == 0,
     child: Container(
       height: 300,
     ),
    Visibility(
      visible: selectedIndex == 1,
      child: Container(
      height: 100,
    )
  ]
)

you can do this inside a column too just replace indexedstack with column.

Related