Flutter需求:下滑隐藏SliverAppBar,仅顶部可展开
实现自定义滚动交互的SliverAppBar
要实现你需要的滚动行为,我们可以通过ScrollController监听滚动方向与位置,结合SliverAppBar的属性动态调整,同时限制仅在滚动到顶部时允许展开AppBar。以下是完整实现代码:
import 'package:flutter/material.dart'; class TestScreen extends StatefulWidget { const TestScreen({super.key}); @override State<TestScreen> createState() => _TestScreenState(); } class _TestScreenState extends State<TestScreen> { late ScrollController _scrollController; bool _showAppBar = true; bool _isAtTop = true; @override void initState() { super.initState(); _scrollController = ScrollController() ..addListener(_handleScroll); } void _handleScroll() { final currentPosition = _scrollController.position.pixels; final direction = _scrollController.position.userScrollDirection; // 更新是否处于页面顶部的状态 setState(() { _isAtTop = currentPosition <= 0; }); // 根据滚动方向控制AppBar显示/隐藏 if (direction == ScrollDirection.reverse) { // 向下滚动,隐藏AppBar if (_showAppBar) { setState(() { _showAppBar = false; }); } } else if (direction == ScrollDirection.forward) { // 向上滚动,显示非展开状态的AppBar if (!_showAppBar) { setState(() { _showAppBar = true; }); } } } @override void dispose() { _scrollController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: CustomScrollView( controller: _scrollController, slivers: [ SliverAppBar( expandedHeight: _isAtTop ? 300 : kToolbarHeight, backgroundColor: Colors.white, floating: false, pinned: _showAppBar, centerTitle: true, title: const Text( "Show on scroll down without expanding", style: TextStyle(color: Colors.black), ), // 仅在顶部时显示展开状态的内容 flexibleSpace: _isAtTop ? FlexibleSpaceBar( background: Container(color: Colors.grey[200]), ) : null, ), // 列表项1 SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20), child: ClipRRect( borderRadius: BorderRadius.circular(10), child: Container(color: Colors.red, height: 400), ), ), ), // 列表项2 SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20), child: ClipRRect( borderRadius: BorderRadius.circular(10), child: Container(color: Colors.deepPurple[400], height: 400), ), ), ), // 列表项3 SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20), child: ClipRRect( borderRadius: BorderRadius.circular(10), child: Container(color: Colors.deepPurple[400], height: 400), ), ), ), // 列表项4 SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20), child: ClipRRect( borderRadius: BorderRadius.circular(10), child: Container(color: Colors.deepPurple[400], height: 400), ), ), ), // 列表项5 SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: 20.0, left: 20, right: 20), child: ClipRRect( borderRadius: BorderRadius.circular(10), child: Container(color: Colors.deepPurple[400], height: 400), ), ), ), ], ), ); } }
核心逻辑说明
- 滚动监听:通过
ScrollController实时获取滚动方向与当前位置,判断用户滚动动作和是否处于页面顶部。 - AppBar状态控制:
- 向下滚动时,设置
_showAppBar = false,让AppBar完全隐藏。 - 向上滚动时,设置
_showAppBar = true,固定显示工具栏高度的AppBar,不会自动展开。 - 仅当滚动到页面顶部时,才允许AppBar展开到设置的
expandedHeight,并显示展开状态的内容。
- 向下滚动时,设置
- 资源管理:在组件销毁时释放
ScrollController,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Emre Akcan
相关产品推荐
相关产品推荐

