Flutter AlertDialog点击按钮后重复弹出问题求助
问题解决:对话框重复弹出的问题
问题根源
你在build方法里通过Future.delayed(Duration.zero, () => _navigateSlide(context))调用对话框,而每次执行setState(比如点击选项切换check状态时)都会触发组件重建,build方法会再次执行,导致对话框被重复调用弹出。
解决方案
把对话框的初始化调用移到initState方法中,因为initState只会在StatefulWidget初始化时执行一次,不会在组件重建时重复触发。同时调整对话框内的逻辑,让Navigator.pop在状态更新后执行,避免顺序冲突。
修改后的完整代码
class ExploreAds extends StatefulWidget { ExploreAds({Key? key}) : super(key: key); @override _ExploreAds createState() => _ExploreAds(); } class _ExploreAds extends State<ExploreAds> { bool show = false; bool check1 = false; bool check2 = false; bool check3 = false; bool check4 = false; final List<String> data = <String>[]; void addValue(txt) { setState(() { data.add('${txt}'); }); print(data); } void removeValue(rmtxt) { setState(() { data.remove('${rmtxt}'); }); print(data); } @override void initState() { super.initState(); // 移到initState,仅在组件初始化时执行一次 Future.delayed(Duration.zero, () => _navigateSlide(context)); } void _navigateSlide(BuildContext context) { final Size size = MediaQuery.of(context).size; showDialog( context: context, builder: (BuildContext context) { return AlertDialog( content: Container( height: 550, child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ SizedBox(height: 10), Expanded( child: Container( child: GridView( padding: EdgeInsets.only(right: 8), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 20, mainAxisSpacing: 20, childAspectRatio: 0.70, ), children: <Widget>[ Stack( children: [ Container( padding: EdgeInsets.only(right: 5, left: 5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), border: Border.all(color: Color(0xffacacac)), ), child: InkWell( onTap: () { setState(() { check1 = !check1; check1 ? addValue('Washing machine') : removeValue('Washing machine'); }); Navigator.pop(context); }, child: Column( children: [ Image.asset('assets/icons/pngwing44.png', width: 115, height: 115), Text('Washing machine') ], ) ), ), Visibility( visible: check1, child: Positioned( top: 5, right: 5, child: Image.asset('assets/icons/tick.png', width: 15), ) ) ], ), Stack( children: [ Container( padding: EdgeInsets.only(right: 5, left: 5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), border: Border.all(color: Color(0xffacacac)), ), child: InkWell( onTap: () { setState(() { check2 = !check2; check2 ? addValue('Air Conditioner') : removeValue('Air Conditioner'); }); Navigator.pop(context); }, child: Column( children: [ Image.asset('assets/icons/pngwing45.png', width: 115, height: 115), Text('Air Conditioner') ], ) ), ), Visibility( visible: check2, child: Positioned( top: 5, right: 5, child: Image.asset('assets/icons/tick.png', width: 15), ) ) ], ), Stack( children: [ Container( padding: EdgeInsets.only(right: 5, left: 5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), border: Border.all(color: Color(0xffacacac)), ), child: InkWell( onTap: () { setState(() { check3 = !check3; check3 ? addValue('Microwave') : removeValue('Microwave'); }); Navigator.pop(context); }, child: Column( children: [ Image.asset('assets/icons/pngwing45.png', width: 115, height: 115), Text('Microwave') ], ) ), ), Visibility( visible: check3, child: Positioned( top: 5, right: 5, child: Image.asset('assets/icons/tick.png', width: 15), ) ) ], ), Stack( children: [ Container( padding: EdgeInsets.only(right: 5, left: 5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), border: Border.all(color: Color(0xffacacac)), ), child: InkWell( onTap: () { setState(() { check4 = !check4; check4 ? addValue('Refrigerators') : removeValue('Refrigerators'); }); Navigator.pop(context); }, child: Column( children: [ Image.asset('assets/icons/pngwing46.png', width: 115, height: 115), Text('Refrigerators') ], ) ), ), Visibility( visible: check4, child: Positioned( top: 5, right: 5, child: Image.asset('assets/icons/tick.png', width: 15), ) ) ], ), ] ), ), ), SizedBox(height: 10), Padding( padding: EdgeInsets.fromLTRB(20, 0, 20, 0), child: ElevatedButton( onPressed: () => Navigator.pop(context), style: ElevatedButton.styleFrom( elevation: 6, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(80.0)), padding: const EdgeInsets.all(0.0), ), child: Container( constraints: const BoxConstraints(minWidth: 88.0, minHeight: 50.0), alignment: Alignment.center, child: const Text( 'Apply', textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 20, ), ), ), ), ) ], ) ) ); }); } @override Widget build(BuildContext context) { final Size size = MediaQuery.of(context).size; final ThemeData themeData = Theme.of(context); const double padding = 25; const sidePadding = EdgeInsets.symmetric(horizontal: padding); return Scaffold( body: Container( padding: sidePadding, width: size.width, height: size.height, child: Text('$data') ), ); } }
额外优化点
- 替换自定义的
addVerticalSpace为标准组件SizedBox(height:10),避免依赖未定义的工具方法 - 将
Navigator.pop从setState回调中移出,确保状态更新完成后再关闭对话框,逻辑更清晰 - 简化
Visibility的条件判断,check1 ? true : false直接写成check1即可
内容的提问来源于stack exchange,提问作者RAF Algowid
相关产品推荐
相关产品推荐

