You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何在SliverAppBar下固定Body内的指定Widget?

解决方案

你的问题出在把需要固定的Widget放在了NestedScrollView的body里——body属于可滚动区域的一部分,所以会跟着列表一起滚动。要让它和SliverAppBar一起固定,得把它移到Sliver头部区域里。

下面给两种可行的实现方式:

方式一:修改NestedScrollView的头部构造器

直接在headerSliverBuilder里添加固定Widget对应的Sliver组件,让它和SliverAppBar一起成为固定头部:

Scaffold(
  body: NestedScrollView(
    headerSliverBuilder: (context, innerBoxIsScrolled) => [
      SliverAppBar(
        leading: InkWell(
          onTap: () => Navigator.of(context).pop(),
          child: const Icon(Icons.arrow_back_ios_new),
        ),
        expandedHeight: 300,
        flexibleSpace: const FlexibleSpaceBar(
          title: Text('All Transactions'),
        ),
        pinned: true,
        floating: true,
      ),
      // 把需要固定的Widget用SliverToBoxAdapter包裹,加入头部Sliver列表
      const SliverToBoxAdapter(
        child: Padding(
          padding: EdgeInsets.all(8.0),
          child: SizedBox(
            height: 50,
            color: Colors.grey,
            child: Center(child: Text('Pinned Widget')),
          ),
        ),
      ),
    ],
    // body直接放列表即可,不需要再包裹Column
    body: showListView(),
  ),
)

方式二:使用CustomScrollView直接组合Sliver组件

如果不需要NestedScrollView的嵌套滚动特性,用CustomScrollView更直接,把所有固定和滚动的Sliver组件按顺序组合:

Scaffold(
  body: CustomScrollView(
    slivers: [
      SliverAppBar(
        leading: InkWell(
          onTap: () => Navigator.of(context).pop(),
          child: const Icon(Icons.arrow_back_ios_new),
        ),
        expandedHeight: 300,
        flexibleSpace: const FlexibleSpaceBar(
          title: Text('All Transactions'),
        ),
        pinned: true,
        floating: true,
      ),
      const SliverToBoxAdapter(
        child: Padding(
          padding: EdgeInsets.all(8.0),
          child: SizedBox(
            height: 50,
            color: Colors.grey,
            child: Center(child: Text('Pinned Widget')),
          ),
        ),
      ),
      // 把ListView转成SliverList
      SliverList(
        delegate: SliverChildBuilderDelegate(
          (context, index) => showListView().children[index],
          childCount: showListView().children.length,
        ),
      ),
    ],
  ),
)

两种方式都能实现:向上滚动时SliverAppBar先收缩到固定高度,之后和下方的固定Widget一起保持不动,只有下面的列表内容滚动。

内容的提问来源于stack exchange,提问作者user22362195

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 03:35:40