CustomScrollView中有多个SliverAppBar

时间:2019-05-05 13:24:21

标签: flutter flutter-sliver

我需要有多个SliverAppBar,每个SliverAppBar在一个视图中都有自己的SliverList。当前,只有第一个SliverAppBar正确响应。

我当然已经在SO和Google上进行了扩展搜索,但是还没有找到解决方案!

  @override
  Widget build(BuildContext context) {
     return Scaffold(
        appBar: AppBar(
          title: Text('Details'),
        ),
        body: CustomScrollView(
          slivers: <Widget>[
            new SliverAppBar(
              floating: true,
              automaticallyImplyLeading: false,
              title: Text('1'),
            ),
            new SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, index) => ListTile(title: Text('Text 1')),
                childCount: 20,
              ),
            ),
            new SliverAppBar(
              automaticallyImplyLeading: false,
              title: Text('2'),
              floating: true,
            ),
            new SliverList(
              delegate: SliverChildBuilderDelegate(
                (context, index) => ListTile(title: Text('Text 2')),
                childCount: 20,
              ),
            ),
          ],
        ),
      );
  }

如果您要滚动,则在滚动列表时,我也希望标题“ 2”也浮动。

1 个答案:

答案 0 :(得分:0)

这似乎是对CustomScrollView的限制。可以解决此问题,但这非常棘手,除非您有固定高度的项目和固定长度的列表。如果是这样,您可以假设整个会话的高度(AppBar高度+每个列表项的高度)。

看看:

class Foo extends StatefulWidget {
  @override
  _FooState createState() => _FooState();
}

class _FooState extends State<Foo> {
  static const double listItemHeight = 50;
  static const int listItemCount = 15;

  static const double sessionHeight = kToolbarHeight + (listItemCount * listItemHeight);

  int floatingAppBarIndex;
  ScrollController controller;

  @override
  void initState() {
    super.initState();
    floatingAppBarIndex = 0;
    controller = ScrollController()..addListener(onScroll);
  }

  void onScroll() {
    double scrollOffset = controller.offset;
    int sessionsScrolled = 0;

    while (scrollOffset > sessionHeight) {
      scrollOffset -= sessionHeight;
      sessionsScrolled++;
    }

    if (sessionsScrolled != floatingAppBarIndex) {
      setState(() {
        floatingAppBarIndex = sessionsScrolled;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Details'),
      ),
      body: CustomScrollView(
        controller: controller,
        slivers: <Widget>[
          new SliverAppBar(
            floating: floatingAppBarIndex == 0,
            automaticallyImplyLeading: false,
            title: Text('1'),
          ),
          new SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return SizedBox(
                  height: listItemHeight,
                  child: ListTile(
                    title: Text('Text 1'),
                  ),
                );
              },
              childCount: listItemCount,
            ),
          ),
          new SliverAppBar(
            floating: floatingAppBarIndex == 1,
            automaticallyImplyLeading: false,
            title: Text('2'),
          ),
          new SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return SizedBox(
                  height: listItemHeight,
                  child: ListTile(
                    title: Text('Text 2'),
                  ),
                );
              },
              childCount: listItemCount,
            ),
          ),
        ],
      ),
    );
  }
}

正如我所说,您仍然可以在具有可变值(项目高度和列表长度)的列表中执行此操作,但这非常棘手。如果是这种情况,建议您使用以下插件之一: https://pub.dartlang.org/packages/sticky_headers https://pub.dartlang.org/packages/flutter_sticky_header