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

觉得有帮助的点点赞😊

相关推荐
0wioiw02 小时前
Flutter基础(前端教程③-跳转)
前端·flutter
Lefan5 小时前
一文了解什么是Dart
前端·flutter·dart
0wioiw05 小时前
Flutter基础(前端教程④-组件拼接)
前端·flutter
木叶丸6 小时前
Flutter 生命周期完全指南
android·flutter·ios
用户7427987737596 小时前
[flutter翻书效果] 用flutter实现一个书籍翻页效果
flutter
技术蔡蔡13 小时前
Flutter和Firebae简单的聊天应用
flutter·全栈·firebase
小蜜蜂嗡嗡1 天前
flutter封装vlcplayer的控制器
前端·javascript·flutter
你听得到112 天前
从需求到封装:手把手带你打造一个高复用、可定制的Flutter日期选择器
前端·flutter
哲科软件2 天前
跨平台开发的抉择:Flutter vs 原生安卓(Kotlin)的优劣对比与选型建议
android·flutter·kotlin
天涯海风2 天前
Kuikly 与 Flutter 的全面对比分析,结合技术架构、性能、开发体验等核心维度
flutter·kuikly