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

Flutter SliverAppBar标题位置与样式切换需求咨询

解决SliverAppBar标题滚动时的位置与样式切换问题

要实现未滚动时标题居左、滚动后居中且两种状态样式不同的效果,你可以通过监听滚动进度,动态控制标题的布局和样式,具体实现如下:

核心思路

利用ScrollController监听滚动偏移,计算SliverAppBar的展开比例(从完全展开到完全折叠的过渡值),然后根据这个比例切换标题的对齐方式、样式甚至文本内容,实现平滑过渡。

完整代码示例

import 'package:flutter/material.dart';

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

  @override
  State<CustomSliverAppBarPage> createState() => _CustomSliverAppBarPageState();
}

class _CustomSliverAppBarPageState extends State<CustomSliverAppBarPage> {
  final ScrollController _scrollController = ScrollController();
  double _expansionRatio = 1.0; // 1.0=完全展开,0.0=完全折叠

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_updateExpansionRatio);
  }

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

  void _updateExpansionRatio() {
    final toolbarHeight = MediaQuery.of(context).padding.top + kToolbarHeight;
    final expandedHeight = 200.0; // 与SliverAppBar的expandedHeight保持一致
    final maxScrollOffset = expandedHeight - toolbarHeight;
    
    // 计算当前滚动偏移对应的展开比例
    final scrollOffset = _scrollController.offset.clamp(0.0, maxScrollOffset);
    setState(() {
      _expansionRatio = 1.0 - (scrollOffset / maxScrollOffset);
    });
  }

  @override
  Widget build(BuildContext context) {
    // 定义两种状态的标题样式
    final expandedStyle = const TextStyle(
      fontSize: 28,
      fontWeight: FontWeight.w600,
      color: Colors.black87,
    );
    final collapsedStyle = const TextStyle(
      fontSize: 20,
      fontWeight: FontWeight.bold,
      color: Colors.white,
    );

    return Scaffold(
      body: CustomScrollView(
        controller: _scrollController,
        slivers: [
          SliverAppBar(
            expandedHeight: 200.0,
            pinned: true,
            backgroundColor: Colors.lightBlue,
            // 关闭默认居中,自定义标题布局
            flexibleSpace: FlexibleSpaceBar(
              titlePadding: EdgeInsets.zero,
              centerTitle: false,
              title: Stack(
                fit: StackFit.expand,
                children: [
                  // 展开状态的标题(居左)
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Padding(
                      padding: const EdgeInsets.only(left: 16, bottom: 16),
                      child: Opacity(
                        opacity: _expansionRatio,
                        child: Text('主页', style: expandedStyle),
                      ),
                    ),
                  ),
                  // 折叠状态的标题(居中)
                  Align(
                    alignment: Alignment.center,
                    child: Opacity(
                      opacity: 1.0 - _expansionRatio,
                      child: Text('主页', style: collapsedStyle),
                    ),
                  ),
                ],
              ),
            ),
          ),
          // 测试滚动内容
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (_, index) => ListTile(title: Text('列表项 $index')),
              childCount: 50,
            ),
          ),
        ],
      ),
    );
  }
}

关键细节说明

  1. 滚动比例计算:
    通过ScrollController获取当前滚动偏移,结合SliverAppBar的expandedHeight和系统Toolbar高度,计算出展开比例_expansionRatio,这个值会随着滚动从1.0平滑降到0.0。

  2. 双标题切换:
    使用Stack叠加两个标题组件,分别对应展开和折叠状态,通过Opacity根据_expansionRatio控制显示透明度,实现平滑过渡效果。如果不需要文本变化,只需保持两个Text内容一致即可。

  3. 平滑过渡优化:
    若想实现更细腻的过渡(比如位置、样式的渐变),可以用Alignment.lerp、TextStyle.lerp替代生硬的切换,示例如下:

    title: Align(
      alignment: Alignment.lerp(
        Alignment.bottomLeft,
        Alignment.center,
        1.0 - _expansionRatio,
      )!,
      child: Padding(
        padding: EdgeInsets.lerp(
          const EdgeInsets.only(left: 16, bottom: 16),
          EdgeInsets.zero,
          1.0 - _expansionRatio,
        )!,
        child: Text(
          '主页',
          style: TextStyle.lerp(expandedStyle, collapsedStyle, 1.0 - _expansionRatio),
        ),
      ),
    ),
    

内容的提问来源于stack exchange,提问作者steind.VY

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:53:17