Flutter实现滚动时标题在页面主体与AppBar间的双向过渡
实现滚动时标题在原位置与AppBar间的过渡效果
这种滚动过渡效果可以通过监听滚动偏移量+动态控制组件的透明度/位置来实现,以下是Flutter中的具体实现方案:
核心思路
- 准备两个相同的标题组件:一个放在页面内容顶部,一个放在AppBar中
- 监听滚动控制器的偏移量,根据滚动距离计算过渡参数(透明度、位置偏移)
- 利用
Opacity和Transform组件实现平滑的视觉过渡
完整代码示例
import 'package:flutter/material.dart'; class TitleScrollTransitionPage extends StatefulWidget { const TitleScrollTransitionPage({super.key}); @override State<TitleScrollTransitionPage> createState() => _TitleScrollTransitionPageState(); } class _TitleScrollTransitionPageState extends State<TitleScrollTransitionPage> { final ScrollController _scrollController = ScrollController(); double _scrollOffset = 0.0; @override void initState() { super.initState(); // 监听滚动偏移 _scrollController.addListener(() { setState(() { _scrollOffset = _scrollController.offset; }); }); } @override void dispose() { _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final double appBarHeight = AppBar().preferredSize.height; // 过渡阈值:页面标题的高度,可根据实际需求调整 const double transitionThreshold = 120.0; // 计算透明度:滚动超过阈值后,AppBar标题完全显示,页面标题完全隐藏 final double titleOpacity = _scrollOffset > transitionThreshold ? 1.0 : _scrollOffset / transitionThreshold; // 页面标题的Y轴偏移:滚动超过阈值后,向上移动至AppBar位置 final double contentTitleYOffset = _scrollOffset > transitionThreshold ? -appBarHeight : 0.0; return Scaffold( appBar: AppBar( title: Opacity( opacity: titleOpacity, child: const Text("我的页面标题"), ), // 随滚动逐渐显示AppBar背景色 backgroundColor: Colors.white.withOpacity(titleOpacity), // 随滚动逐渐显示阴影 elevation: titleOpacity > 0 ? 4 : 0, ), body: SingleChildScrollView( controller: _scrollController, child: Column( children: [ // 页面内的标题组件 Transform.translate( offset: Offset(0, contentTitleYOffset), child: Opacity( opacity: 1 - titleOpacity, child: Container( height: transitionThreshold, padding: const EdgeInsets.symmetric(horizontal: 16), alignment: Alignment.centerLeft, child: const Text( "我的页面标题", style: TextStyle( fontSize: 32, fontWeight: FontWeight.bold, ), ), ), ), ), // 页面主体内容 ...List.generate(50, (index) { return ListTile( title: Text("列表项 $index"), leading: const Icon(Icons.list), ); }), ], ), ), ); } }
关键细节说明
- 过渡阈值:
transitionThreshold设置为页面标题的高度,确保滚动到标题完全移出视图时完成过渡 - 动画参数:通过
titleOpacity同步控制两个标题的透明度,contentTitleYOffset让页面标题平滑移动到AppBar位置 - AppBar样式过渡:随滚动逐渐显示背景色和阴影,让整体过渡更自然
内容的提问来源于stack exchange,提问作者Gabriel Ángel Canals Salleras
相关产品推荐
相关产品推荐

