Flutter SliverAppBar实现下拉显示bar 上拉隐藏

转载请声明出处!!!

什么是SliverAppBar

SliverAppBar 类似于Android中的CollapsingToolbarLayout,可以轻松实现页面头部展开、合并的效果。 与AppBar大部分的属性重合,相当于AppBar的加强版

现在大部分app在一些页面都会有在用户在下拉页面的时候固定显示bar而在页面顶部的隐藏此部分,这个功能是可以用SliverAppBar和监听页面滚动来实现的

效果图:

首先创建一个ScrollController因为我们要用到CustomScrollView,在创建一个bool来判断是否要显示bar

添加监听页面滚动 判断的范围可以根据业务需求更改

ini 复制代码
void _onScroll() {
  // 获取当前滚动位置的偏移量
  final offset = _scrollController.offset;

  // 当滚动偏移量超过10,并且当前显示 AppBar 状态为 false 时,更新状态使 AppBar 显示
  if (offset > 10 && !showAppBar) {
    setState(() => showAppBar = true);
  }
  // 当滚动偏移量小于等于10,并且当前显示 AppBar 状态为 true 时,更新状态使 AppBar 隐藏
  else if (offset <= 10 && showAppBar) {
    setState(() => showAppBar = false);
  }
}

通过SliverLayoutBuilder来控制是否要显示SliverAppbar,SliverLayoutBuilder是一个可以在 Sliver 中动态构建 UI 的组件,允许你基于 SliverConstraints 动态调整 Sliver 布局。

less 复制代码
SliverLayoutBuilder(
  builder: (context, constraints) {
    return showAppBar
        ? SliverAppBar(
            pinned: true, //是否固定
            backgroundColor: Colors.white,
            elevation: 0,
            automaticallyImplyLeading: false,
            toolbarHeight: 43.h,
            flexibleSpace: FlexibleSpaceBar(
              collapseMode: CollapseMode.pin,
              background: _buildHeaderBar(),
            ),
          )
        : SliverToBoxAdapter(child: SizedBox.shrink());
  },
),

全部代码:

less 复制代码
class MySliverPage extends StatefulWidget {
  @override
  _MySliverPageState createState() => _MySliverPageState();
}

class _MySliverPageState extends State<MySliverPage> {
  final ScrollController _scrollController = ScrollController();
  bool showAppBar = false;

  void _onScroll() {
    // 获取当前滚动位置的偏移量
    final offset = _scrollController.offset;

    // 当滚动偏移量超过10,并且当前显示 AppBar 状态为 false 时,更新状态使 AppBar 显示
    if (offset > 10 && !showAppBar) {
      setState(() => showAppBar = true);
    }
    // 当滚动偏移量小于等于10,并且当前显示 AppBar 状态为 true 时,更新状态使 AppBar 隐藏
    else if (offset <= 10 && showAppBar) {
      setState(() => showAppBar = false);
    }
  }

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_onScroll);
  }

  @override
  void dispose() {
    _scrollController.removeListener(_onScroll);
    _scrollController.dispose();
    super.dispose();
  }

  Widget _buildHeaderBar() {
    return Column(
      children: [
        30.h.heightBox,
        Row(
          children: [
            15.w.widthBox,
            ClipRRect(
              borderRadius: BorderRadius.circular(15),
              child: SizedBox(
                width: 30.w,
                height: 30.w,
                child: CachedNetworkImage(
                  imageUrl: 'https://img2.baidu.com/it/u=3901868821,1751410039&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
                  fit: BoxFit.cover,
                ),
              ),
            ),
            10.w.widthBox,
            Text("lynxx", style: TextStyle(fontSize: 12.sp, color: Colors.black)),
            Spacer(),
            IconButton(
              onPressed: () {},
              icon: Icon(Icons.settings, color: Colors.black, size: 15),
            ),
          ],
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        controller: _scrollController,
        slivers: [
          // 通过 SliverLayoutBuilder 来控制是否插入 SliverAppBar
          SliverLayoutBuilder(
            builder: (context, constraints) {
              return showAppBar
                  ? SliverAppBar(
                      pinned: true, //是否固定
                      backgroundColor: Colors.white,
                      elevation: 0,
                      automaticallyImplyLeading: false,
                      toolbarHeight: 43.h,
                      flexibleSpace: FlexibleSpaceBar(
                        collapseMode: CollapseMode.pin,
                        background: _buildHeaderBar(),
                      ),
                    )
                  : SliverToBoxAdapter(child: SizedBox.shrink());
            },
          ),

          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => ListTile(title: Text("Item $index")),
              childCount: 50,
            ),
          ),
        ],
      ),
    );
  }
}

觉得有帮助的点点赞😊

相关推荐
0wioiw05 小时前
Flutter基础()
flutter
肥肥呀呀呀9 小时前
flutter 视频通话flutter_webrtc
flutter
明似水10 小时前
2025年Flutter项目管理技能要求
flutter
肥肥呀呀呀12 小时前
flutter使用命令生成BinarySize分析图
flutter
程序猿阿伟12 小时前
《数字分身进化论:React Native与Flutter如何打造沉浸式虚拟形象编辑》
flutter·react native·react.js
怀君12 小时前
Flutter——数据库Drift开发详细教程(六)
数据库·flutter
明似水1 天前
2025年Flutter初级工程师技能要求
flutter
程序猿阿伟1 天前
《从像素到身份:Flutter如何打通社交应用人脸识别的技术闭环》
flutter
周胡杰2 天前
鸿蒙接入flutter环境变量配置windows-命令行或者手动配置-到项目的创建-运行demo项目
javascript·windows·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
程序猿阿伟2 天前
《React Native与Flutter:社交应用中用户行为分析与埋点统计的深度剖析》
flutter·react native·react.js