8
votes

Whenever I scroll in my listview, I get this error spammed in console:

ScrollController not attached to any scroll views.
'package:flutter/src/widgets/scroll_controller.dart':
Failed assertion: line 110 pos 12: '_positions.isNotEmpty'

I've been trying to fix this all day and I'd like to have someone else take a look at it. There are more problems with this code, but right now I'm mainly interested in fixing this error.

I've tried to use Listview.builder, checking for hController.hasClients and many more small things. They didn't seem to change anything

class MyHome extends StatefulWidget {
  @override
  MyHomeState createState() => new MyHomeState();
}

class MyHomeState extends State<MyHome> with SingleTickerProviderStateMixin {
  ScrollController hController;
  ScrollController tController;
  ScrollController fController;
  ScrollController bController;

  @override
  void initState() {
    super.initState();
    hController = new ScrollController()..addListener(_scrollListener);
    tController = new ScrollController()..addListener(_scrollListener);
    fController = new ScrollController()..addListener(_scrollListener);
    bController = new ScrollController()..addListener(_scrollListener);
  }

  @override
  void dispose() {
    super.dispose();
    hController.removeListener(_scrollListener);
    tController.removeListener(_scrollListener);
    fController.removeListener(_scrollListener);
    bController.removeListener(_scrollListener);
  }
  @override
  Widget build(BuildContext context) {
    return new DefaultTabController(
        length: 4,
        child: new Scaffold(
          //Removed AppBar for readability
          body: new TabBarView(
            children: [
              new Container(// hot
                child: ListView(
                    controller: hController,
                    children: <Widget>[
                      Utils.show("hot")
                    ],
                ),
              ),
              new Container( //Trending
                child: ListView(
                  controller: tController,
                  children: <Widget>[
                    Utils.show("trending")
                  ],
                ),
              ),
              new Container( //Fresh
                child: ListView(
                  controller: fController,
                  children: <Widget>[
                    Utils.show("fresh")
                  ],
                ),
              ),
              new Container( //Best
                child: ListView(
                  controller: bController,
                  children: <Widget>[
                    Utils.show("best")
                  ],
                ),
              ),
            ],
          ),
        ));
  }
  void _scrollListener() {
    if (hController.position.extentAfter == 0.0) {
      setState(() {
        Utils.show("hot");
      });
    }else if (tController.position.extentAfter == 0.0) {
      setState(() {
        Utils.show("trending");
      });
    } else if (fController.position.extentAfter == 0.0) {
      setState(() {
        Utils.show("fresh");
      });
    } else if (bController.position.extentAfter == 0.0) {
      setState(() {
        Utils.show("best");
      });
    }
  }

}

Edit: For some clarity, the first time I posted this code, I used tController twice. This was ofcourse a mistake, but did not solve the error. The error happens when scrolling in every one of the four listviews.

5
Can you edit your post to add 'scroll_controller.dart' file? The error seems to lurk there. - Ananth
@Ananth This is a default flutter file, the error refers to : ScrollPosition get position { assert(_positions.isNotEmpty, 'ScrollController not attached to any scroll views.'); assert(_positions.length == 1, 'ScrollController attached to multiple scroll views.'); return _positions.single; } - Karsten

5 Answers

15
votes

To avoid such type of errors use the getter

ScrollController.hasClient

If this is false, then members that interact with the [ScrollPosition],such as [position], [offset], [animateTo], and [jumpTo], must not be called.

for example:

    if (_controller.hasClients) {
      _controller.animateTo(
      ...
    }
4
votes

The problem is inside _scrollListener.

When you are checking controllers in if-else there is only one view at the scene. Means only one listview is rendered & only one scrollcontroller is completely setup. But in your code they are checking all scrollcontroller's positions in single function. Thats why you are getting this error. First check if controller have the positions, which it will only have if the controller is attached & view is rendered correctly. After that check for extentAfter value.

Exa -

if (hController.positions.length > 0 && tController.position.extentAfter == 0.0) {
}
else if (tController.positions.length > 0 && tController.position.extentAfter == 0.0) {
}

& so on

0
votes

If you paste your code correctly - it seems there can be mistake:

new Container(// hot
  child: ListView(
    controller: tController,
    children: <Widget>[
      Utils.show("hot")
    ],
  ),
),
new Container( //Trending
  child: ListView(
    controller: tController,
    children: <Widget>[
      Utils.show("trending")
    ],
  ),
),

You have used tController two times and haven't used hController

0
votes

Update your flutter sdk it will solve this problem That is work for me run this on your cmd - flutter update

0
votes

check controller does not have client ant then delay jump:

if (!_scrollController.hasClients) {
      _scrollController.animateTo(_scrollController.position.maxScrollExtent,
        duration: const Duration(milliseconds: 500),
        curve: Curves.easeInOut);
    }