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

觉得有帮助的点点赞😊

相关推荐
书弋江山2 小时前
flutter 跨平台编码库 protobuf 工具使用
android·flutter
程序员老刘·2 小时前
Flutter 3.35 更新要点解析
flutter·ai编程·跨平台开发·客户端开发
tangweiguo030519872 小时前
Flutter vs Android:页面生命周期对比详解
flutter
tangweiguo030519872 小时前
Flutter网络请求实战:Retrofit+Dio完美解决方案
flutter
来来走走5 小时前
Flutter开发 webview_flutter的基本使用
android·flutter
落魄的Android开发6 小时前
Flutter以模块化适配 HarmonyOS方案的实现步骤
flutter
tangweiguo030519877 小时前
Flutter GetX 全面指南:状态管理、路由与依赖注入的最佳实践
flutter
来来走走11 小时前
Flutter Form组件的基本使用
android·flutter
fouryears_234171 天前
Flutter InheritedWidget 详解:从生命周期到数据流动的完整解析
开发语言·flutter·客户端·dart
LinXunFeng1 天前
Flutter - 详情页 TabBar 与模块联动?秒了!
前端·flutter·开源