Flutter - 带有 CupertinoSliverNavigationBar 的 ScrollController,从 largeTitle 到 smallTitle 不起作用 NestedScrollView 类通知监听器

问题描述

当我在 ListView 中使用 ScrollController 时,它会阻止 CupertinoSliverNavigationBar largeTitle 转换为 smallTitle。但是,如果我删除了 scrollController,问题就会消失。我认为这可能是库比蒂诺图书馆中的一个错误

代码演示了该问题:

 ScrollController scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return CupertinopageScaffold(
      child: nestedScrollView(
        headerSliverBuilder: (BuildContext context,bool innerBoxIsScrolled) {
          return <Widget>[
            CupertinoSliverNavigationBar(
              largeTitle: Text('Large Title'),),];
        },body: ListView.builder(
            controller: scrollController,itemCount: 50,itemBuilder: (BuildContext context,int index) {
              return Container(
                height: 50,child: Center(child: Text('Entry ${index}')),);
            }),);
  }

现在,如果我删除了 scrollController,问题就消失了:

ScrollController scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return CupertinopageScaffold(
      child: nestedScrollView(
        headerSliverBuilder: (BuildContext context,body: ListView.builder(
            //controller: scrollController,);
  }

解决方法

这是预期行为,因为 NestedScrollView 旨在管理所有其他子滚动视图的滚动位置:

NestedScrollView 类

一个滚动视图,其中可以嵌套其他滚动视图, 它们的滚动位置具有内在的联系。

因此,您无法使用单个 ScrollController 控制其子视图的位置。但是,您可以提供一个供 NestedScrollView 一次性管理。

通知监听器

除了使用ScrollController之外,还有一种方法可以监听内部滚动视图的滚动事件。您可以将 ListView 放在 NotificationListener 中并检查它提供的滚动信息。

@override
Widget build(BuildContext context) {
  return CupertinoPageScaffold(
    child: NestedScrollView(
      headerSliverBuilder: (BuildContext context,bool innerBoxIsScrolled) {
        return <Widget>[
          CupertinoSliverNavigationBar(
            largeTitle: Text('Large Title'),),];
      },body: NotificationListener<ScrollNotification>(
        onNotification: (ScrollNotification scrollInfo) {
          if (scrollInfo.metrics.pixels ==
              scrollInfo.metrics.maxScrollExtent) {
            print('Reached the bottom');
          }
          return;
        },child: ListView.builder(
          itemCount: 50,itemBuilder: (BuildContext context,int index) {
            return Container(
              height: 50,child: Center(child: Material(child: Text('Entry $index'))),);
          },);
}