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

Flutter 如何在向下滚动时让ListView内的指定容器固定在屏幕顶部

Flutter实现ListView内指定容器吸顶的解决方案

你需要的吸顶效果可以通过Flutter原生的Sliver系列组件实现,无需依赖第三方库,性能最优,实现逻辑如下:

核心实现思路

使用CustomScrollView统一管理所有滚动内容,通过SliverPersistentHeader的吸顶属性实现tabs固定效果,整体结构完全匹配你的布局要求:

  • 最外层Scaffold配置固定的appBar和底部navBar
  • CustomScrollView内依次放置可滚动的image1、吸顶tabs、列表项三个模块
  • 开启SliverPersistentHeader的pinned参数,即可实现tabs滚动到AppBar下方时自动固定,不会跟随滚动消失

最简实现代码

import 'package:flutter/material.dart';

class StickyTabPage extends StatelessWidget {
  const StickyTabPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 固定顶部的appBar
      appBar: AppBar(title: const Text("吸顶效果演示"), centerTitle: true),
      // 固定底部的navBar
      bottomNavigationBar: NavigationBar(
        destinations: const [
          NavigationDestination(icon: Icon(Icons.home), label: "首页"),
          NavigationDestination(icon: Icon(Icons.person), label: "我的"),
        ],
      ),
      body: CustomScrollView(
        slivers: [
          // 模块1:跟随滚动消失的image1
          const SliverToBoxAdapter(
            child: ColoredBox(
              color: Colors.grey,
              child: Center(child: Text("image1 区域", style: TextStyle(color: Colors.white, fontSize: 24))),
              height: 200,
            ),
          ),
          // 模块2:吸顶固定的tabs
          SliverPersistentHeader(
            pinned: true, // 核心参数:开启吸顶固定
            delegate: _StickyTabDelegate(
              height: 50,
              child: Container(
                color: Colors.white,
                child: const TabBar(
                  labelColor: Colors.blue,
                  unselectedLabelColor: Colors.grey,
                  tabs: [
                    Tab(text: "分类1"),
                    Tab(text: "分类2"),
                    Tab(text: "分类3"),
                  ],
                ),
              ),
            ),
          ),
          // 模块3:下方的列表项
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => ListTile(title: Text("列表项 $index")),
              childCount: 50,
            ),
          )
        ],
      ),
    );
  }
}

// 自定义SliverPersistentHeader代理,配置吸顶组件的高度和内容
class _StickyTabDelegate extends SliverPersistentHeaderDelegate {
  final Widget child;
  final double height;

  _StickyTabDelegate({required this.child, required this.height});

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return SizedBox.expand(child: child);
  }

  @override
  double get maxExtent => height;

  @override
  double get minExtent => height;

  @override
  bool shouldRebuild(covariant _StickyTabDelegate oldDelegate) {
    return oldDelegate.height != height || oldDelegate.child != child;
  }
}

适配多Tab切换场景

如果tabs需要对应不同的列表页面,只需要把上面代码中的SliverList替换为SliverFillRemaining,内部嵌套TabBarView即可实现多Tab滚动切换的效果,滚动逻辑依然会联动,吸顶效果不会受影响。

备选方案

如果现有项目已经用了普通ListView,改造成本较高,可以使用第三方组件库实现单节点吸顶,将需要吸顶的tabs包裹在对应组件的header参数中即可,仅适合无需复杂滚动联动的简单场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 08:36:04