Skip to content

ScrollController attached to multiple scroll views Failed assertion: line 109 pos 12: '_positions.length == 1' #80664

Closed

Description

@matamune94

My code

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  PageController _pageController;
  ScrollController _scrollController;
  double offset = 0.0;

  @override
  void initState(){
    super.initState();
    _pageController = PageController(initialPage: 0);
    _scrollController = ScrollController();
    _scrollController.addListener(this.swapPageListener);
  }

  void swapPageListener() {
    WidgetsBinding.instance.addPostFrameCallback((_){ 
      offset = _scrollController.offset;
      // _pageController.hasClients
      if (offset > _scrollController.position.maxScrollExtent + 100) {
        if(_pageController.hasClients) {
          _pageController.animateToPage(1, duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
          // _pageController.animateTo(offset, duration: duration, curve: curve)
        }
      }
      if (offset < _scrollController.position.minScrollExtent - 100) {
        _pageController.previousPage(duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
      }
    });
  }
  // @override
  // void dispose() {
  //   super.dispose();
  //   _pageController.dispose();
  // }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: PageView.builder(
          controller: _pageController,
          scrollDirection: Axis.vertical,
          itemCount: 2,
          physics: NeverScrollableScrollPhysics(),
          itemBuilder: (context, idx) {
            if(idx == 0) {
              return _screen1();
            } else {
              return _screen2();
            }
          }
        ),
      ),
    );
  }

  Widget _screen1() {
    return SingleChildScrollView(
      physics: BouncingScrollPhysics(),
      controller: _scrollController,
      child: Container(
        height: 1000.0,
        color: Colors.red,
        child: Center(
          child: Text('screen 1'),
        ),
      ),
    );
  }

  Widget _screen2() {
    return SingleChildScrollView(
      physics: BouncingScrollPhysics(),
      controller: _scrollController,
      child: Container(
        height: 1000.0,
        color: Colors.green,
        child: Center(
          child: Text('screen 2'),
        ),
      ),
    );
  }
}

fluuter docker -v

[√] Flutter (Channel stable, 2.0.4, on Microsoft Windows [Version 10.0.19042.928], locale en-US)
    • Flutter version 2.0.4 at C:\src\flutter
    • Framework revision b1395592de (2 weeks ago), 2021-04-01 14:25:01 -0700
    • Engine revision 2dce47073a
    • Dart version 2.12.2

[!] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
    • Android SDK at C:\Users\Admin\AppData\Local\Android\Sdk
    • Platform android-30, build-tools 30.0.1
    • ANDROID_HOME = C:\Users\Admin\AppData\Local\Android\Sdk
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    X Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Android Studio (version 4.0)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 47.1.2
    • Dart plugin version 193.7547
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] VS Code (version 1.55.2)
    • VS Code at C:\Users\Admin\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.21.0

[√] Connected device (3 available)
    • Android SDK built for x86 64 (mobile) • emulator-5554 • android-x64    • Android 9 (API 28) (emulator)
    • Chrome (web)                          • chrome        • web-javascript • Google Chrome 87.0.4280.88
    • Edge (web)                            • edge          • web-javascript • Microsoft Edge 89.0.774.77

! Doctor found issues in 1 category.

I make error

ScrollController attached to multiple scroll views.
'package:flutter/src/widgets/scroll_controller.dart':
Failed assertion: line 109 pos 12: '_positions.length == 1'

when use _pageController.animateToPage,

me

Activity

  1. Jahidul007 commented on Apr 18, 2021

    @Jahidul007
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      MyApp({Key key}) : super(key: key);
    
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State {
      PageController _pageController;
      ScrollController _scrollController;
      double offset = 0.0;
    
      @override
      void initState(){
        super.initState();
        _pageController = PageController(initialPage: 0);
        _scrollController = ScrollController();
        _scrollController.addListener(this.swapPageListener);
    
      }
    
      void swapPageListener() {
    
        offset = _scrollController.offset;
        setState(() {
          _pageController.hasClients;
          if (offset > _scrollController.position.maxScrollExtent + 100) {
            _pageController.animateToPage(1, duration: Duration(milliseconds: 500), curve: Curves.ease);
          }
          if (offset <_scrollController.position.minScrollExtent - 100) {
            _pageController.animateToPage(0, duration: Duration(milliseconds: 500), curve: Curves.ease);
          }
        });
    
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: PageView.builder(
                controller: _pageController,
                scrollDirection: Axis.vertical,
                pageSnapping: true,
                itemCount: 2,
                physics: PageScrollPhysics(),
                itemBuilder: (context, idx) {
                  if(idx == 0) {
                    return _screen1();
                  } else {
                    return _screen2();
                  }
                }
            ),
          ),
        );
      }
    
      Widget _screen1() {
        return SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          controller: _scrollController,
          child: Container(
            height: 1000.0,
            color: Colors.red,
            child: Center(
              child: Text('screen 1'),
            ),
          ),
        );
      }
    
      Widget _screen2() {
        return SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          controller: _scrollController,
          child: Container(
            height: 1000.0,
            color: Colors.green,
            child: Center(
              child: Text('screen 2'),
            ),
          ),
        );
      }
    }
    
  2. matamune94 commented on Apr 18, 2021

    @matamune94
    Author
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatefulWidget {
      MyApp({Key key}) : super(key: key);
    
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State {
      PageController _pageController;
      ScrollController _scrollController;
      double offset = 0.0;
    
      @override
      void initState(){
        super.initState();
        _pageController = PageController(initialPage: 0);
        _scrollController = ScrollController();
        _scrollController.addListener(this.swapPageListener);
    
      }
    
      void swapPageListener() {
    
        offset = _scrollController.offset;
        setState(() {
          _pageController.hasClients;
          if (offset > _scrollController.position.maxScrollExtent + 100) {
            _pageController.animateToPage(1, duration: Duration(milliseconds: 500), curve: Curves.ease);
          }
          if (offset <_scrollController.position.minScrollExtent - 100) {
            _pageController.animateToPage(0, duration: Duration(milliseconds: 500), curve: Curves.ease);
          }
        });
    
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: PageView.builder(
                controller: _pageController,
                scrollDirection: Axis.vertical,
                pageSnapping: true,
                itemCount: 2,
                physics: PageScrollPhysics(),
                itemBuilder: (context, idx) {
                  if(idx == 0) {
                    return _screen1();
                  } else {
                    return _screen2();
                  }
                }
            ),
          ),
        );
      }
    
      Widget _screen1() {
        return SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          controller: _scrollController,
          child: Container(
            height: 1000.0,
            color: Colors.red,
            child: Center(
              child: Text('screen 1'),
            ),
          ),
        );
      }
    
      Widget _screen2() {
        return SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          controller: _scrollController,
          child: Container(
            height: 1000.0,
            color: Colors.green,
            child: Center(
              child: Text('screen 2'),
            ),
          ),
        );
      }
    }
    

    It not working. I think setState is not the problem.

  3. matamune94 commented on Apr 18, 2021

    @matamune94
    Author

    Hello, I have found the solution to this problem.

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    PageController _pageController;
    
    class MyApp extends StatefulWidget {
      MyApp({Key key}) : super(key: key);
    
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
    
      @override
      void initState(){
        super.initState();
        _pageController = PageController(initialPage: 0);
      }
    
    
      // @override
      // void dispose() {
      //   super.dispose();
      //   _pageController.dispose();
      // }
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: PageView.builder(
              controller: _pageController,
              scrollDirection: Axis.vertical,
              itemCount: 2,
              physics: NeverScrollableScrollPhysics(),
              itemBuilder: (context, idx) {
                return Screen(pageKey: idx,);
              }
            ),
          ),
        );
      }
    }
    
    class Screen extends StatefulWidget {
      Screen({Key key, this.pageKey}) : super(key: key);
      final pageKey;
    
      @override
      _ScreenState createState() => _ScreenState();
    }
    
    class _ScreenState extends State<Screen> {
      ScrollController _scrollController;
    
      @override
      void initState(){
        super.initState();
        _scrollController = ScrollController();
        _scrollController.addListener(this.swapPageListener);
      }
    
      void swapPageListener() {
        if (_scrollController.offset > _scrollController.position.maxScrollExtent + 100) {
          _pageController.animateToPage(1, duration: Duration(milliseconds: 400), curve: Curves.easeInOut);
        }
        if (_scrollController.offset < _scrollController.position.minScrollExtent - 100) {
          _pageController.animateToPage(0, duration: Duration(milliseconds: 400), curve: Curves.easeInOut);
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          controller: _scrollController,
          child: Container(
            height: 1000.0,
            color: Colors.green,
            child: Center(
              child: Text('screen ${widget.pageKey}'),
            ),
          ),
        );
      }
    }
    
  4. iapicca commented on Apr 18, 2021

    @iapicca

    @matamune94
    I'm glad you found a solution,
    but this issue doesn't seem to describe a bug or a feature request
    the issue is likely to depend from you implementation
    as you are clearly assigning the same controller to 2 different ScrollView

      Widget _screen1() {
        return SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          controller: _scrollController,
          child: Container(
            height: 1000.0,
            color: Colors.red,
            child: Center(
              child: Text('screen 1'),
            ),
          ),
        );
      }
    
      Widget _screen2() {
        return SingleChildScrollView(
          physics: BouncingScrollPhysics(),
          controller: _scrollController,
          child: Container(
            height: 1000.0,
            color: Colors.green,
            child: Center(
              child: Text('screen 2'),
            ),
          ),
        );
      }

    if you need assistance with your code please follow the link I want help writing my application in the new issue menu
    or ask on discord, reddit and slack

    as a personal opinion, I recommend to use a state management for this type of situation
    logic should not be handled in the widgets!

  5. tiloc commented on Apr 18, 2021

    @tiloc

    This might be similar to #74372

  6. pedromassangocode commented on Apr 19, 2021

    @pedromassangocode

    As said above, this issue seems to be caused by your implementation as you are assigning the same controller into two different scroll views.

    You may get some help if you post it on Stack Overflow and if you need help with your code, please see https://www.reddit.com/r/flutterhelp/
    Closing, as this isn't an issue with Flutter itself. If you disagree, please write in the comments and I will reopen it.
    Thank you

  7. added
    r: invalidIssue is closed as not valid
    and removed
    in triagePresently being triaged by the triage team
    on Apr 19, 2021
  8. kevin4dhd commented on Apr 24, 2021

    @kevin4dhd

    Same problem, any solution without creating two controllers?

  9. github-actions commented on Aug 2, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  10. locked as resolved and limited conversation to collaborators on Aug 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    r: invalidIssue is closed as not valid

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions