如何创建一个具有上方固定元素和下方浮动元素的 SliverAppBar?

How to create a SliverAppBar, that has a upper pinned and lower floating element?

所以我想创建一个 SliverAppBar,其中上半部分固定并始终显示。 即使未到达列表顶部,下部也必须浮动并在向下滚动时显示。

让它对我有用的唯一方法是在彼此之上添加 2 个 sliverappbar,但我觉得这不是最好的方法。那么如何正确完成呢?

  return Scaffold(
      body: NestedScrollView(
        body: ListView.builder(
            itemBuilder: (context, index) => Text(index.toString())),
        headerSliverBuilder: (context, hasScrolled) {
          return [
            const SliverAppBar(
              title: Text('pinned'),
              pinned: true,
              centerTitle: true,
            ),
            const SliverAppBar(
              floating: true,
              snap: true,
              title: Text('floating'),
            ),
          ];
        },
      ),
    );

所以从视觉上看,这就是我要找的东西,我只是不确定实现。

这是你想要的吗,顺便说一句,它不是动画的。


class CUstomScrolling extends StatefulWidget {
  const CUstomScrolling({Key? key}) : super(key: key);

  @override
  _CUstomScrollingState createState() => _CUstomScrollingState();
}

class _CUstomScrollingState extends State<CUstomScrolling> {
  final ScrollController controller = ScrollController();

  bool _showNavBar = true;

  @override
  void initState() {
    super.initState();

    controller.addListener(() {
      if (controller.hasClients) {
        if (controller.position.userScrollDirection ==
                ScrollDirection.forward &&
            !_showNavBar) {
          setState(() {
            _showNavBar = true;
          });
        } else if (controller.position.userScrollDirection ==
                ScrollDirection.reverse &&
            _showNavBar) {
          setState(() {
            _showNavBar = false;
          });
        }
      }
    });
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: NestedScrollView(
        body: ListView.builder(
          controller: controller,
          itemBuilder: (context, index) => Text(
            index.toString(),
          ),
        ),
        headerSliverBuilder: (context, hasScrolled) {
          return [
            const SliverAppBar(
              title: Text('pinned'),
              pinned: true,
              centerTitle: true,
            ),
            if (_showNavBar)
              const SliverAppBar(
                pinned: false,
                floating: true,
                title: Text('floating'),
              ),
          ];
        },
      ),
    );
  }
}

这样就可以了:

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Title')),
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
            floating: true,
            title: Text('Test'),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => ListTile(title: Text('Item #$index')),
              childCount: 1000,
            ),
          ),
        ],
      ),
    );