I make error when using animateToPage

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

I try to use _pageController.hasClients but it not working.

Please have a look in 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 {
  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;
    _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,
            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'),
        ),
      ),
    );
  }
}

Thanks in advance

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}'),
        ),
      ),
    );
  }
}


Solution 1: Jahidul Islam

please check out your solution

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'),
        ),
      ),
    );
  }
}


Solution 2: Shoaib Khan

Here is the answer provided by me which is working fine

Check out the answer here.

https://stackoverflow.com/a/70672454/14155787