一个ScrollController附加到多个滚动视图中,失败的断言:第109行,第12个位置:'_positions.length == 1'。

3

我在使用animateToPage时出现了错误。

一个ScrollController附加到多个滚动视图。 'package:flutter/src/widgets/scroll_controller.dart': 失败断言: 第109行, 位置12: '_positions.length == 1'

我尝试使用_pageController.hasClients,但它不起作用。

请看我的代码-

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

预先感谢您。

你好,我已经找到了解决这个问题的方法。

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}'),
        ),
      ),
    );
  }
}
3个回答

2
请查看您的解决方案。
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'),
        ),
      ),
    );
  }
}

我试了你的代码,但还是出现了错误。 - Jubei Yagyu
复制我的代码并粘贴,希望能正常工作。在我的电脑上,它是有效的。 - Jahidul Islam
是的,它可以工作,但仍然会返回一个错误。 - Jubei Yagyu
请查看您的swapPageListener()方法,并将代码包装在set state中。 - Jahidul Islam
我编辑了答案,请再检查一次。 - Jahidul Islam
显示剩余7条评论

0

0
在我的情况下,我在多个页面中重复使用同一个PageView,并且每当我调用.animateToPage()时,它会显示错误,而我犯的错误很简单。
错误:
static final PageController _pageController = PageController();

修复:
late PageController _pageController;

 @override
  void initState() {
     _pageController = PageController();
...

在这里,我只是为每个页面初始化了新的控制器,在它们初始化时调用了这个公共页面视图小部件。对于滚动控制器,根据您的情况也是一样适用的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接