ScrollController当我离开具有控制 a的页面时,我的 Flutter 应用程序抛出异常(ScrollController 附加到多个滚动视图)NestedScrollView,我不确定我做错了什么。
我用下面的一个简单示例重新创建了异常。我可以从FirstPageto导航SecondPage(也可以选择返回)就好了,但是当我从SecondPageto导航时ThirdPage会抛出异常。这SecondPage是包含我CollapsingAppBarPage认为有问题的自定义小部件的页面。CollapsingAppBarPage在此示例中进行了简化,但在我的真实应用程序中,它会根据滚动位置更改组件的颜色/大小。在此示例中,当_scrollController.offset导航开始到ThirdPage. 另外,我知道 FirstPage 和 ThirdPage 可以是无状态的而不是 StatefulWidgets,但我想让它尽可能像我的应用程序。这是我的完整工作示例。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: FirstPage(),
    );
  }
}
class FirstPage extends StatefulWidget {
  @override
  _FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("First Page"),
      ),
      body: Center(
        child: RaisedButton(
          child: Text("Navigate Next"),
          onPressed: () async {
            await Navigator.push(context,
                MaterialPageRoute(builder: (context) => SecondPage())
            );
          },
        ),
      ),
    );
  }
}
class SecondPage extends StatefulWidget {
  @override
  _SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
  @override
  Widget build(BuildContext context) {
    return Material(
      child: CollapsingAppBarPage(
        titleText: "Second Page",
        bodyCreator: (context) {
          return ListView(
            children: <Widget>[
              Center(
                child: RaisedButton(
                  child: Text("Navigate Next"),
                  onPressed: () async {
                    await Navigator.push(context,
                        MaterialPageRoute(builder: (context) => ThirdPage())
                    );
                  },
                ),
              )
            ],
          );
        },
      ),
    );
  }
}
class ThirdPage extends StatefulWidget {
  @override
  _ThirdPageState createState() => _ThirdPageState();
}
class _ThirdPageState extends State<ThirdPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text("Third Page")
        ),
        body: Container()
    );
  }
}
typedef CollapsingAppBarBodyCreator = Widget Function(BuildContext context);
class CollapsingAppBarPage extends StatefulWidget {
  final String titleText;
  final CollapsingAppBarBodyCreator bodyCreator;
  CollapsingAppBarPage({
    Key key,
    this.titleText,
    @required this.bodyCreator,
  }) : super(key: key);
  @override
  _CollapsingAppBarPageState createState() => _CollapsingAppBarPageState();
}
class _CollapsingAppBarPageState extends State<CollapsingAppBarPage> {
  static const _kExpandedHeight = 200.0;
  ScrollController _scrollController;
  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController()
      ..addListener(() {
        setState(() {
          // force a refresh so the app bar can be updated
        });
      });
  }
  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return NestedScrollView(
      controller: _scrollController,
      headerSliverBuilder: _createSliverAppBar,
      body: widget.bodyCreator(context),
    );
  }
  List<Widget> _createSliverAppBar(BuildContext context, bool innerBoxIsScrolled) {
    // change the icon color as the page scrolls
    var collapsePercent = _getAppBarCollapsePercent();
    int rgb = ((1.0 - collapsePercent) * 255).round();
    var color = Color.fromARGB(255, rgb, rgb, rgb);
    return <Widget>[
      SliverAppBar(
        expandedHeight: _kExpandedHeight,
        pinned: true,
        iconTheme: IconThemeData(color: color),
        title: Text(widget.titleText),
      )
    ];
  }
  double _getAppBarCollapsePercent() {
    if (!_scrollController.hasClients)
      return 0.0;
    return (_scrollController.offset / (_kExpandedHeight - kToolbarHeight)).clamp(0.0, 1.0);
  }
}
这是异常的截断跟踪:
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown building Builder(dirty):
flutter: ScrollController attached to multiple scroll views.
flutter: 'package:flutter/src/widgets/scroll_controller.dart': Failed assertion: line 111 pos 12:
flutter: '_positions.length == 1'
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter:   https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #2      ScrollController.position (package:flutter/src/widgets/scroll_controller.dart:111:12)
flutter: #3      ScrollController.offset (package:flutter/src/widgets/scroll_controller.dart:118:24)
flutter: #4      _CollapsingAppBarPageState._getAppBarCollapsePercent (package:flutter_scroll_test/main.dart:160:31)
flutter: #5      _CollapsingAppBarPageState._createSliverAppBar (package:flutter_scroll_test/main.dart:142:27)
flutter: #6      NestedScrollView._buildSlivers (package:flutter/src/widgets/nested_scroll_view.dart:271:20)
flutter: #7      _NestedScrollViewState.build.<anonymous closure> (package:flutter/src/widgets/nested_scroll_view.dart:347:29)
flutter: #8      Builder.build (package:flutter/src/widgets/basic.dart:5736:41)
flutter: #9      StatelessElement.build (package:flutter/src/widgets/framework.dart:3774:28)
flutter: #10     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)