Tovi Newman
Tovi Newman

Reputation: 715

Flutter: How can I use DraggableScrollableActuator.reset AND the ScrollController from DraggableScrollableSheet for a nested list?

I am getting this error.

The following assertion was thrown building _InheritedResetNotifier(dirty):
flutter: ScrollController attached to multiple scroll views.
flutter: 'package:flutter/src/widgets/scroll_controller.dart':
flutter: Failed assertion: line 111 pos 12: '_positions.length == 1'

It seems I can either attach DraggableScrollableSheet's ScrollController to the nested list OR use DraggableScrollableActuator.reset(context) to reset the extent. I don't see why I can't do both. Is this a bug? Is there a work around or another way?

Here is my code:

class InterfaceSelector extends StatefulWidget {
  @override
  InterfaceSelectorState createState() => InterfaceSelectorState();
}

class InterfaceSelectorState extends State<InterfaceSelector> {
  double initialChildSize = 0.5;
  double minChildSize = 0.5;
  double maxChildSize = 0.7;

  @override
  Widget build(BuildContext context) {
    return DraggableScrollableActuator(
      child: DraggableScrollableSheet(
        initialChildSize: initialChildSize,
        minChildSize: minChildSize,
        maxChildSize: maxChildSize,
        builder: (BuildContext ctx, ScrollController scrollController) {
          return SingleChildScrollView(
            controller: scrollController,
            child: Container(
              height: MediaQuery.of(context).size.longestSide * .7,
              color: Theme.of(ctx).primaryColor,
              child: DefaultTabController(
                length: 4,
                child: Column(
                  children: <Widget>[
                    Material(
                      color: Theme.of(ctx).accentColor,
                      child: TabBar(
                        tabs: [
                          Tab(text: "One"),
                          Tab(text: "Two"),
                          Tab(text: "Three"),
                          Tab(text: "Four"),
                        ],
                      ),
                    ),
                    Expanded(
                      child: TabBarView(
                        children: [
                          One(),
                          Two(),
                          Three(scrollController),
                          Four(),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

class Three extends StatefulWidget {
  ScrollController scrollController;
  Three(this.scrollController);
  @override
  _ThreeState createState() => _ThreeState();
}

class _ThreeState extends State<Three> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    Stuff stuff = Provider.of<Stuff>(context);
    return Column(
      children: <Widget>[
        MaterialButton(onPressed: () {
          DraggableScrollableActuator.reset(context);
        }),
        Expanded(
          child: GridView.builder(
            controller: widget.scrollController,
            padding: const EdgeInsets.all(10),
            itemCount: stuff.all.length,
            itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
              value: stuff.all[i],
              key: UniqueKey(),
              child: StuffCard(i, stuff.all[i], stuff),
            ),
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 3,
              crossAxisSpacing: 10,
              mainAxisSpacing: 10,
            ),
          ),
        ),
      ],
    );
  }
}

Upvotes: 1

Views: 1378

Answers (1)

Alex Kuzmin
Alex Kuzmin

Reputation: 725

Your GridView doesn't need scrolling - scrolling is provided by your SingleChildScrollView. Don't pass the scrollController to GridView, set physics: NeverScrollableScrollPhysics(), in your grid builder instead:

GridView.builder(
        physics: NeverScrollableScrollPhysics(),
        padding: const EdgeInsets.all(10),
        itemCount: stuff.all.length,
        itemBuilder: (ctx, i) => ChangeNotifierProvider.value(
          value: stuff.all[i],
          key: UniqueKey(),
          child: StuffCard(i, stuff.all[i], stuff),
        ),
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
          crossAxisSpacing: 10,
          mainAxisSpacing: 10,
        ),
      ),

Upvotes: 2

Related Questions