You need to enable JavaScript to run this app. Flutter实现SliverAppBar展开时FlexibleSpace带底部圆角、折叠时无圆角
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现SliverAppBar展开时FlexibleSpace带底部圆角、折叠时无圆角

可切换圆角状态的SliverAppBar实现方案

核心逻辑:不要直接给SliverAppBar外层包裹固定圆角装饰,否则折叠后圆角会永久保留,不符合需求,正确做法是监听滚动进度,动态调整背景容器的圆角半径。

实现步骤

  • 给关联的CustomScrollView绑定ScrollController,实时获取滚动偏移量
  • 计算AppBar的可折叠区间:最大可滚动偏移量为expandedHeight - 状态栏高度 - AppBar固定高度,超出这个区间说明AppBar已经完全折叠为固定状态
  • 根据折叠进度计算当前圆角半径:完全展开时为目标圆角值,完全折叠时为0,中间状态按比例平滑过渡
  • 带圆角的装饰仅作用于FlexibleSpaceBar的background容器,不要覆盖到折叠后的固定AppBar区域

完整可运行代码

class RoundedSliverAppBarPage extends StatefulWidget {
  const RoundedSliverAppBarPage({super.key});

  @override
  State<RoundedSliverAppBarPage> createState() => _RoundedSliverAppBarPageState();
}

class _RoundedSliverAppBarPageState extends State<RoundedSliverAppBarPage> {
  late final ScrollController _scrollController;
  // 和SliverAppBar配置保持一致的参数
  final double _expandedHeight = 250;
  final double _maxCornerRadius = 20;
  // 动态变化的圆角值
  double _currentRadius = 20;

  @override
  void initState() {
    super.initState();
    _scrollController = ScrollController();
    _scrollController.addListener(_calcCornerRadius);
  }

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

  void _calcCornerRadius() {
    // 获取状态栏高度,避免计算偏移量偏差
    final double statusBarHeight = MediaQuery.of(context).padding.top;
    // 可折叠的最大滚动距离:滚到这个值时AppBar完全折叠为固定状态
    final double maxFoldOffset = _expandedHeight - statusBarHeight - kToolbarHeight;
    // 限制偏移量在合法区间,避免顶部越界下拉导致的负值
    final double clampedOffset = _scrollController.offset.clamp(0.0, maxFoldOffset);
    // 计算折叠进度比例
    final double foldProgress = clampedOffset / maxFoldOffset;
    setState(() {
      _currentRadius = _maxCornerRadius * (1 - foldProgress);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        controller: _scrollController,
        slivers: [
          SliverAppBar(
            leading: const BackButton(color: Colors.black),
            pinned: true,
            snap: false,
            floating: false,
            expandedHeight: _expandedHeight,
            backgroundColor: const Color(0xffEBEBEB),
            flexibleSpace: FlexibleSpaceBar(
              centerTitle: true,
              title: const Text(
                "Collapsing Toolbar",
                style: TextStyle(
                  color: Colors.red,
                  fontSize: 16.0,
                ),
              ),
              // 动态圆角仅作用于背景容器
              background: Container(
                decoration: BoxDecoration(
                  color: const Color(0xffEBEBEB),
                  borderRadius: BorderRadius.only(
                    bottomLeft: Radius.circular(_currentRadius),
                    bottomRight: Radius.circular(_currentRadius),
                  ),
                ),
                child: const FlutterLogo(),
              ),
            ),
          ),
          // 替换为实际业务列表内容即可
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) => ListTile(title: Text("列表项 $index")),
              childCount: 30,
            ),
          ),
        ],
      ),
    );
  }
}

适配说明

  • 如果不需要下拉越界的弹性效果,可以把CustomScrollView的physics设置为ClampingScrollPhysics
  • 圆角值可以根据设计需求调整_maxCornerRadius的数值即可
  • 如果需要圆角过渡更丝滑,可以把包裹背景的Container替换为AnimatedContainer,设置较短的duration(比如100毫秒)

内容的提问来源于stack exchange,提问作者Abu Taha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 16:24:03