Flutter中Scaffold.showSnackBar不显示问题求助
Flutter SnackBar 不显示问题排查与修复
问题根源
你的页面根组件使用的是Material,而ScaffoldMessenger需要依托Scaffold提供的上下文才能正常工作。没有Scaffold的情况下,当前context无法找到对应的ScaffoldMessenger实例,导致showSnackBar调用后没有任何视觉反馈,虽然print能正常输出。
修复方案
将页面根组件替换为Scaffold,Scaffold内部会自动集成ScaffoldMessenger,确保SnackBar能正常显示。同时修正一些代码规范和逻辑细节:
- 替换根组件为
Scaffold,将背景色设置到Scaffold的backgroundColor属性 - 规范State类命名(符合Flutter大驼峰命名约定)
- 修正
setState的语法错误 - 优化本地加载年龄后的有效性标记逻辑
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:workout_app/Screens/Components/Sign_Up_Screens/screen1.dart'; import 'package:workout_app/Screens/Components/Sign_Up_Screens/screen3.dart'; class Screen2 extends StatefulWidget { @override State<StatefulWidget> createState() => Screen2State(); } class Screen2State extends State<Screen2> { void returnScreen(BuildContext context) { Navigator.of(context).pushReplacement( MaterialPageRoute( fullscreenDialog: true, builder: (context) => Screen1(), ), ); } @override void initState() { loadData(); super.initState(); } @override void dispose() { super.dispose(); } int age = 10; bool nextValid = false; void toast(String text) { print(text); final scaffold = ScaffoldMessenger.of(context); scaffold.showSnackBar( SnackBar( content: Text(text), behavior: SnackBarBehavior.floating, ), ); } void submitData() async { if (!nextValid) { toast('Please input your age'); return; } SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setInt('age', age); Navigator.of(context).pushReplacement( MaterialPageRoute( fullscreenDialog: true, builder: (context) => SingleSelectListViewWithLogo(items: [ 'Tone Up - You want visible muscles with as little mass as possible and a low body fat percentage', 'Bulk Up - You want large, defined muscles, with a low percentage of body fat', 'Get Jacked - You want to lift an insane amount of weight and don\'t care about body fat or muscle definition' ]), ), ); } void loadData() async { SharedPreferences prefs = await SharedPreferences.getInstance(); try { int? x = prefs.getInt('age'); print(x); if (x != null) { setState(() => age = x); setState(() => nextValid = true); } } catch (e) { print('Load age error: $e'); } } @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return Scaffold( backgroundColor: Colors.grey, body: Stack( children: <Widget>[ Positioned( top: size.height * .06, left: size.width * .03, child: InkWell( onTap: () { returnScreen(context); }, child: Image.asset( alignment: Alignment.topLeft, "assets/images/back2.png", width: size.width * .07, ), ), ), Positioned( top: size.height * .09, left: size.width * .42, child: const Text( style: TextStyle(fontSize: 30, color: Color.fromARGB(255, 4, 3, 3)), 'Next,' ) ), Positioned( top: size.height * .15, left: size.width * .16, child: const Text( style: TextStyle(fontSize: 20, color: Color.fromARGB(255, 76, 74, 74)), 'Lets customize your workout!' ), ), Positioned ( top: size.height * .23, left: size.width * .28, child: Image.asset( "assets/images/age.png", width: size.width * .4 ) ), Positioned( top: size.height * .55, left: size.width * .15, child: const Text( style: TextStyle(fontSize: 25, color: Color.fromARGB(255, 21, 17, 17)), 'What\'s your current age?' ), ), Positioned ( top: size.height * .7, left: size.width * .1, child: SliderTheme( data: const SliderThemeData( trackHeight: 30, inactiveTrackColor: Color.fromARGB(255, 255, 255, 255), activeTrackColor: Color.fromARGB(255, 50, 45, 45), thumbColor: Colors.black, disabledActiveTrackColor: Colors.black, disabledInactiveTrackColor: Colors.black12, thumbShape: RoundSliderThumbShape(enabledThumbRadius: 25.0), ), child: SizedBox( width: size.width * .8, child: Slider( label: "Select Age", value: age.toDouble(), onChanged: (value) { setState(() { age = value.toInt(); nextValid = true; }); }, min: 10, max: 99, ), ), ), ), Positioned ( top: size.height * .62, left: size.width * .28, child: Text( age.toString(), style: const TextStyle( fontSize: 40.0, ), ), ), Positioned ( top: size.height * .64, left: size.width * .42, child: const Text ( 'years old', style: TextStyle( fontSize: 25.0, ), ), ), Positioned( top: size.height * .86, left: size.width * .1, child: SizedBox( width: size.width * .8, height: size.height * .08, child: ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all<Color>(!nextValid ? const Color.fromRGBO(69, 75, 85, 1) : const Color.fromARGB(255, 0, 147, 246)), ), child: const Text('Continue', style: TextStyle(fontSize: 20), ), onPressed: submitData, ), ), ), ], ), ); } }
额外说明
- 添加
SnackBarBehavior.floating属性,避免SnackBar被底部按钮遮挡 - 修正类名的大驼峰命名,符合Dart/Flutter编码规范
- 在
loadData中加载到本地年龄后,自动标记为有效状态,减少用户重复操作 - 简化了按钮点击事件的调用方式
内容的提问来源于stack exchange,提问作者Promaster
相关产品推荐
相关产品推荐

