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,
            ),
          ),
        ],
      ),
    );
  }
}

觉得有帮助的点点赞😊

相关推荐
ZH154558913111 分钟前
Flutter for OpenHarmony Python学习助手实战:Web开发框架应用的实现
python·学习·flutter
晚霞的不甘12 分钟前
Flutter for OpenHarmony 构建简洁高效的待办事项应用 实战解析
flutter·ui·前端框架·交互·鸿蒙
百锦再23 分钟前
Vue高阶知识:利用 defineModel 特性开发搜索组件组合
前端·vue.js·学习·flutter·typescript·前端框架
廖松洋(Alina)1 小时前
【收尾以及复盘】flutter开发鸿蒙APP之成就徽章页面
flutter·华为·开源·harmonyos·鸿蒙
ZH15455891311 小时前
Flutter for OpenHarmony Python学习助手实战:机器学习算法实现的实现
python·学习·flutter
廖松洋(Alina)2 小时前
【收尾以及复盘】flutter开发鸿蒙APP之打卡日历页面
flutter·华为·开源·harmonyos·鸿蒙
廖松洋(Alina)2 小时前
【收尾以及复盘】flutter开发鸿蒙APP之本月数据统计页面
flutter·华为·开源·harmonyos·鸿蒙
renke33642 小时前
Flutter for OpenHarmony:构建一个 Flutter 数字迷宫游戏,从随机路径生成到认知训练系统的完整工程实践与跨学科深度解析
flutter·游戏
子春一2 小时前
Flutter for OpenHarmony:构建一个 Flutter 数字消消乐游戏,深入解析网格状态管理、合并算法与重力系统
算法·flutter·游戏
程序员老刘·15 小时前
Android Studio Otter 3 发布:日常开发选AS还是Cursor?
flutter·android studio·ai编程·跨平台开发·客户端开发