You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义Flutter的SliverAppBar实现三星笔记滚动效果?

实现三星笔记风格顶部栏(SliverAppBar方案+替代方案)

一、SliverAppBar实现方案

1. 反向滚动效果实现

三星笔记的反向滚动指列表向下滚动时,顶部栏内部元素产生反向偏移的视觉效果。你可以通过ScrollController监听滚动偏移,在flexibleSpace中动态调整组件位置实现:

final ScrollController _scrollController = ScrollController();
double _offset = 0.0;

@override
void initState() {
  super.initState();
  _scrollController.addListener(() {
    setState(() {
      // 限制偏移范围,避免过度移动
      _offset = _scrollController.offset.clamp(0.0, 60.0);
    });
  });
}

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

在SliverAppBar的flexibleSpace中使用Transform实现反向位移:

SliverAppBar(
  expandedHeight: 120.0,
  pinned: true,
  flexibleSpace: FlexibleSpaceBar(
    background: Transform.translate(
      offset: Offset(0, -_offset * 0.5), // 反向滚动系数可自行调整
      child: Container(
        padding: const EdgeInsets.only(left: 20, bottom: 20),
        alignment: Alignment.bottomLeft,
        child: const Text(
          'All notes',
          style: TextStyle(fontSize: 16),
        ),
      ),
    ),
    title: AnimatedOpacity(
      opacity: _offset > 30 ? 1.0 : 0.0, // 滚动到指定偏移时显示大标题
      duration: const Duration(milliseconds: 200),
      child: const Text(
        'All notes',
        style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
      ),
    ),
    centerTitle: false,
  ),
),

2. 标题切换逻辑

上述代码已包含标题切换逻辑:通过滚动偏移_offset控制两个标题的透明度与位置。当滚动偏移超过30时,小字号标题随反向滚动移出视野,大字号标题平滑显示。你可以根据需求调整阈值、动画时长和反向滚动系数,让过渡更贴合三星笔记的效果。

二、非SliverAppBar替代方案

如果不想依赖SliverAppBar,可采用Stack + ListView的组合,手动监听滚动来控制顶部栏行为,自由度更高:

final ScrollController _scrollController = ScrollController();
double _offset = 0.0;

@override
void initState() {
  super.initState();
  _scrollController.addListener(() {
    setState(() {
      _offset = _scrollController.offset.clamp(0.0, 80.0);
    });
  });
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Stack(
      children: [
        // 列表内容
        ListView.builder(
          controller: _scrollController,
          padding: const EdgeInsets.only(top: 120), // 给顶部栏预留空间
          itemCount: 50,
          itemBuilder: (context, index) => ListTile(title: Text('Note $index')),
        ),
        // 自定义顶部栏
        Positioned(
          top: -_offset * 0.3, // 反向滚动效果
          left: 0,
          right: 0,
          child: Container(
            height: 120 - _offset, // 随滚动收缩高度
            color: Theme.of(context).scaffoldBackgroundColor,
            padding: const EdgeInsets.only(left: 20, bottom: 20),
            alignment: Alignment.bottomLeft,
            child: Stack(
              children: [
                // 小字号标题,随滚动移出
                Transform.translate(
                  offset: Offset(0, _offset),
                  child: const Text('All notes', style: TextStyle(fontSize: 16)),
                ),
                // 大字号标题,随滚动显示
                Opacity(
                  opacity: _offset / 80, // 0到1的平滑过渡
                  child: const Text('All notes', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
                ),
              ],
            ),
          ),
        ),
      ],
    ),
  );
}

这种方案完全脱离Sliver组件的约束,适合需要自定义更复杂交互逻辑的场景。


内容的提问来源于stack exchange,提问作者arash shakibaee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 00:15:40