Flutter for OpenHarmony 实战之基础组件:第十八篇 布局终极者 CustomScrollView 与 Slivers

Flutter for OpenHarmony 实战之基础组件:第十八篇 布局终极者 CustomScrollView 与 Slivers

前言

在 Flutter 中,ListView 实际上是一个封装好的便捷组件,但它有一个局限性:它只能包含一种滚动模式。

当页面结构变得复杂(例如:一部分是网格 Grid,一部分是列表 List,还有一个高度会变化的吸顶头部 AppBar),我们就需要使用 CustomScrollView

CustomScrollView 中,所有的子组件都不再是普通的 Widget,而是 Sliver(意为"碎片/薄片")。Sliver 具有特殊的本领:它们能在滚动过程中,精确地告诉父容器自己还有多少部分可见,从而实现极其复杂的联动动效。

本文你将学到

  • CustomScrollView 的基本骨架
  • SliverAppBar 的高级用法(吸顶、伸缩背景)
  • 如何在同一个页面混合 SliverListSliverGrid
  • 适配 OpenHarmony 的"沉浸式"头部窗口设计
  • 实战:模仿主流电商 App 的"商详页"布局

一、Sliver 体系的核心组件

1.1 CustomScrollView:碎片的容器

它是所有 Sliver 的父节点。

1.2 SliverAppBar:会变魔术的顶栏

这是 CustomScrollView 最强大的排头兵。

  • floating: 向下滑动时顶栏是否立即出现。
  • pinned: 滚动到顶时是否吸顶。
  • expandedHeight: 展开时的最大高度。

1.3 SliverList / SliverGrid

对应 ListViewGridView 的 Sliver 版本。


二、基础代码结构

dart 复制代码
CustomScrollView(
  slivers: [
    // 1. 吸顶顶栏
    SliverAppBar(
      pinned: true,
      expandedHeight: 200.0,
      flexibleSpace: FlexibleSpaceBar(
        title: const Text('鸿蒙精选'),
        background: Image.network('...', fit: BoxFit.cover),
      ),
    ),
    
    // 2. 网格区域
    SliverGrid(
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        mainAxisSpacing: 10,
        crossAxisSpacing: 10,
      ),
      delegate: SliverChildBuilderDelegate(
        (context, index) => Container(color: Colors.orange[100 * (index % 9)]),
        childCount: 10,
      ),
    ),
    
    // 3. 列表区域
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (context, index) => ListTile(title: Text('资讯条目 $index')),
        childCount: 20,
      ),
    ),
  ],
)

三、进阶:SliverPersistentHeader 吸顶工具

如果你想让页面中间的某个组件(比如"分类筛选栏")在滑到顶部时也吸顶,可以使用 SliverPersistentHeader

它需要一个 SliverPersistentHeaderDelegate 来描述吸顶时的最大和最小高度。

dart 复制代码
class MyHeaderDelegate extends SliverPersistentHeaderDelegate {
  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      color: Colors.white,
      alignment: Alignment.center,
      child: const Text('💡 我是吸顶筛选栏'),
    );
  }

  @override
  double get maxExtent => 50.0; // 展开高度

  @override
  double get minExtent => 50.0; // 吸顶高度

  @override
  bool shouldRebuild(oldDelegate) => false;
}

四、OpenHarmony 平台适配:沉浸式体验

在鸿蒙系统中,我们追求"沉浸式"视觉,即应用的背景色能延伸到系统的状态栏(刘海区域)。

4.1 配合 SliverAppBar 实现沉浸式

当我们使用 SliverAppBar 时,系统会自动处理大部分状态栏的显示。但在鸿蒙上,我们需要注意:

  1. 设置状态栏透明

    dart 复制代码
    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent, // 设置状态栏透明
    ));
  2. 活用 FlexibleSpaceBar

    在鸿蒙平板等大尺寸设备上,expandedHeight 可以设置得更有视觉冲击力。

图 1:利用 SliverAppBar 实现背景图片延伸至状态栏的沉浸式视觉效果,并在滚动时自动收起吸顶。


五、实战:商详页混合布局

我们来实现一个典型的"商品详情页"雏形。

dart 复制代码
class OhosProductDetail extends StatelessWidget {
  const OhosProductDetail({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          // 1. 商品图片大图 + 吸顶按钮
          SliverAppBar(
            pinned: true,
            expandedHeight: 350.0,
            backgroundColor: Colors.white,
            elevation: 0,
            leading: const Icon(Icons.arrow_back_ios, color: Colors.black),
            actions: [const Icon(Icons.share, color: Colors.black), const SizedBox(width: 16)],
            flexibleSpace: FlexibleSpaceBar(
              background: Image.network('https://images.unsplash.com/photo-1542291026-7eec264c27ff', fit: BoxFit.cover),
            ),
          ),
          
          // 2. 商品标题区 (SliverToBoxAdapter 可以把普通 Widget 转为 Sliver)
          const SliverToBoxAdapter(
            child: Padding(
              padding: EdgeInsets.all(16.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('鸿蒙智联 运动跑鞋', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
                  SizedBox(height: 8),
                  Text('¥ 599.00', style: TextStyle(fontSize: 20, color: Colors.orange)),
                ],
              ),
            ),
          ),
          
          // 3. 吸顶参数切换栏
          SliverPersistentHeader(
            pinned: true,
            delegate: _SliverHeaderDelegate(
              child: Container(
                color: Colors.grey[100],
                child: const TabBar(
                  tabs: [Tab(text: "介绍"), Tab(text: "规格"), Tab(text: "评论")],
                  labelColor: Colors.blue,
                ),
              ),
            ),
          ),
          
          // 4. 详情内容长列表
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => Container(
                height: 200,
                margin: const EdgeInsets.all(16),
                color: Colors.blue[50 * (index % 9 + 1)],
                child: Center(child: Text('商品详情图 $index')),
              ),
              childCount: 10,
            ),
          ),
        ],
      ),
    );
  }
}

六、总结

Slivers 是 Flutter 布局中最高级的一环,它赋予了我们"像素级"控制滚动的能力。

核心要点:

  1. CustomScrollView:作为入口,承载所有 Sliver。
  2. SliverAppBar:实现炫酷的顶栏缩放和吸顶。
  3. SliverToBoxAdapter:这是"黏合剂",让你可以把任何普通的 Container、Column 扔进 Sliver 列表里。
  4. 适配思维 :针对鸿蒙多设备,利用 SliverAppBar 的伸缩特性,在手机端保持精简,在平板端展示更丰富的 Banner 视野。

下一篇预告

页面的功能架子搭好了,但现在看起来依然很单调。我们要如何给应用增加一点"质感"?比如像卡片一样的分块、带阴影的漂浮感、以及点击时的水波纹反馈。
《Flutter for OpenHarmony 实战之基础组件:第十九篇 质感布局 Card 与交互水波纹》

让我们把 UI 做得更精致!


🌐 欢迎加入开源鸿蒙跨平台社区开源鸿蒙跨平台开发者社区

相关推荐
菜鸟不学编程4 小时前
鸿蒙中的 AR/VR 开发与场景创建
ar·vr·harmonyos
程序员Ctrl喵6 小时前
异步编程:Event Loop 与 Isolate 的深层博弈
开发语言·flutter
Swift社区6 小时前
鸿蒙应用上架流程经验
华为·harmonyos
@不误正业6 小时前
OpenHarmony集成AI Agent实战:打造鸿蒙智能助理
人工智能·华为·harmonyos
前端不太难7 小时前
Flutter 如何设计可长期维护的模块边界?
flutter
小蜜蜂嗡嗡8 小时前
flutter列表中实现置顶动画
flutter
始持9 小时前
第十二讲 风格与主题统一
前端·flutter
始持9 小时前
第十一讲 界面导航与路由管理
flutter·vibecoding
始持9 小时前
第十三讲 异步操作与异步构建
前端·flutter
新镜9 小时前
【Flutter】 视频视频源横向、竖向问题
flutter