如何在NestedScrollView滚动到底部时移除Bottom Sheet组件?
实现滚动到底部移除BottomSheet的方案
要实现滚动到NestedScrollView底部时移除BottomSheet,核心思路是监听滚动位置,判断是否到达底部后,通过状态变量控制BottomSheet的显示/隐藏。
步骤1:添加状态变量管理BottomSheet显示
在你的State类中添加布尔变量,用于控制BottomSheet的显示状态:
bool _showBottomSheet = true;
步骤2:修改BottomSheet的条件渲染
将原有的bottomSheet属性改为根据状态变量动态渲染:
bottomSheet: _showBottomSheet ? Container( height: 40, width: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: FractionalOffset.bottomCenter, colors: <Color>[ Colors.white.withOpacity(0.1), Colors.white, ], stops: [0, 1], ), ), ) : null,
步骤3:监听滚动事件判断是否到达底部
在buildWidget(context, 'contacts')外层包裹NotificationListener<ScrollNotification>,监听滚动位置并更新状态:
修改后的代码片段:
NotificationListener<ScrollNotification>( onNotification: (scrollNotification) { // 预留10像素偏移避免滚动精度导致的误判 if (scrollNotification is ScrollUpdateNotification && scrollNotification.metrics.pixels >= scrollNotification.metrics.maxScrollExtent - 10) { if (_showBottomSheet) { setState(() { _showBottomSheet = false; }); } } // 如需滚动回顶部时重新显示BottomSheet,可取消以下注释 // else if (scrollNotification.metrics.pixels <= 100 && !_showBottomSheet) { // setState(() { // _showBottomSheet = true; // }); // } return true; }, child: buildWidget(context, 'contacts'), )
完整修改后的代码
// 状态变量 bool _showBottomSheet = true; // ... 其他业务代码 ... NestedScrollView( headerSliverBuilder: (context, isScrolled) { return [ SliverPersistentHeader( pinned: true, floating: false, delegate: ChooseUsersHeaderDelegate( widgetList: Container( color: Colors.white, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ /// Search Box buildSearch(), ], ), ), minHeight: selectedContactId.isNotEmpty ? 135 : 60, maxHeight: selectedContactId.isNotEmpty ? 135 : 60, parentContext: context, ), ), ]; }, body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Text( 'allContacts', style: GoogleFonts.montserrat( fontSize: 14, fontWeight: FontWeight.w500, color: primaryColor, fontStyle: FontStyle.normal, ), ).tr(), Column( mainAxisAlignment: MainAxisAlignment.start, children: [ isLoading ? ReusableLoadingContact() : NotificationListener<OverscrollIndicatorNotification>( onNotification: (overScroll) { overScroll.disallowIndicator(); return true; }, child: NotificationListener<ScrollNotification>( onNotification: (scrollNotification) { if (scrollNotification is ScrollUpdateNotification && scrollNotification.metrics.pixels >= scrollNotification.metrics.maxScrollExtent - 10) { if (_showBottomSheet) { setState(() { _showBottomSheet = false; }); } } return true; }, child: buildWidget(context, 'contacts'), ), ), ], ), ], ), ], ), ), bottomSheet: _showBottomSheet ? Container( height: 40, width: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: FractionalOffset.bottomCenter, colors: <Color>[ Colors.white.withOpacity(0.1), Colors.white, ], stops: [0, 1], ), ), ) : null,
关键说明
- 滚动判断时预留10像素偏移,避免因滚动精度问题导致频繁触发状态更新。
- 确保
buildWidget返回的是可滚动组件(如ListView、GridView),否则无法触发滚动通知。
内容的提问来源于stack exchange,提问作者Kim San
相关产品推荐
相关产品推荐

