Flutter自定义NavBar中GestureDetector点击Container无响应问题排查
问题原因及修复方案
核心问题
你的_isMapsSelected变量定义在build()方法内部,每次调用setState()都会重新执行build,这会把变量重新初始化为true——也就是说你点击"Discover"修改状态后,立刻又被重置回去了,所以看起来手势没生效。
修复步骤
把状态变量移到State类的成员位置,确保它不会在build时被反复初始化:
class SearchPage extends StatefulWidget { const SearchPage({super.key}); @override State<SearchPage> createState() => _SearchPageState(); } class _SearchPageState extends State<SearchPage> { // 将变量移至此处,作为State类的成员变量 bool _isMapsSelected = true; @override Widget build(BuildContext context) { // 移除原build方法内的bool _isMapsSelected = true; return Scaffold( extendBodyBehindAppBar: true, backgroundColor: Colors.grey, appBar: AppBar( elevation: 0, backgroundColor: Colors.transparent, title: ClipRRect( borderRadius: const BorderRadius.only( topLeft: Radius.circular(FizzinConstants.radius), topRight: Radius.circular(FizzinConstants.radius)), child: BackdropFilter( filter: ImageFilter.blur( sigmaX: 15.0, sigmaY: 25.0, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ GestureDetector( behavior: HitTestBehavior.translucent, onTap: () => { setState(() { _isMapsSelected = true; }) }, child: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(FizzinConstants.radius), color: _isMapsSelected ? FizzinColors.cVividBlue : Colors.transparent, ), child: Text( 'Maps', style: _isMapsSelected ? const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold) : const TextStyle( color: FizzinColors.cDarkGrey, fontSize: 14, fontWeight: FontWeight.bold), ), ), ), GestureDetector( behavior: HitTestBehavior.translucent, onTap: () => { setState(() { _isMapsSelected = false; }) }, child: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(FizzinConstants.radius), color: _isMapsSelected ? Colors.transparent : FizzinColors.cVividBlue, ), child: Text( 'Discover', style: _isMapsSelected ? const TextStyle( color: FizzinColors.cDarkGrey, fontSize: 14, fontWeight: FontWeight.bold) : const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold), ), )), ], ))), ), body: _isMapsSelected ? const MapContentTab() : const SearchContentTab(), ); } }
额外说明
- 之前使用AbsorbPointer完全没必要,问题根本不是手势被拦截,而是状态变量的作用域错误。
- 状态变量必须放在State类的成员区域,才能在多次build调用之间保持状态。
内容的提问来源于stack exchange,提问作者Seb
相关产品推荐
相关产品推荐

