Flutter双击视频流切换方向后,AppBar与底部导航栏无法隐藏求助
解决Flutter双击切换屏幕方向时AppBar和底部导航栏无法隐藏的问题
问题根源
核心问题是状态管理范围不匹配:你使用的全局变量isPortrait,其对应的setState调用仅触发了直播流页面(SettingsCameraUser)的重建,但包含Scaffold的主页面无法感知到全局变量的变化,因此AppBar和bottomNavigationBar的显示状态无法同步更新。
解决方案
将状态提升到包含MaterialApp和Scaffold的主页面,通过回调函数让子页面触发主页面的状态更新,从而重建Scaffold来控制导航栏的显示。同时补充系统UI的隐藏逻辑,优化横屏体验。
1. 修改主页面(包含Scaffold的Widget)
class MainApp extends StatefulWidget { @override _MainAppState createState() => _MainAppState(); } class _MainAppState extends State<MainApp> { // 将状态移至主页面State中,废弃全局变量 bool isPortrait = true; // 定义切换方向的统一逻辑 void toggleOrientation() { setState(() { isPortrait = !isPortrait; }); // 设置屏幕方向 if (isPortrait) { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); // 竖屏恢复系统UI显示 SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); } else { SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]); // 横屏隐藏状态栏和导航栏 SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); } } @override Widget build(BuildContext context) { return MaterialApp( home: DefaultTabController( length: 4, child: Scaffold( appBar: isPortrait ? PreferredSize( preferredSize: Size.fromHeight(120), child: AppBarService(), ) : null, bottomNavigationBar: isPortrait ? menu() : null, body: TabBarView( physics: NeverScrollableScrollPhysics(), children: [ MainPage(), HistoryPage(), DataBaseUser(), // 将切换逻辑回调传给直播流页面 SettingsCameraUser(onToggleOrientation: toggleOrientation), ], ), ), ), ); } }
2. 修改直播流页面(SettingsCameraUser)
// 接收主页面传来的回调参数 class SettingsCameraUser extends StatelessWidget { final VoidCallback onToggleOrientation; const SettingsCameraUser({Key? key, required this.onToggleOrientation}) : super(key: key); @override Widget build(BuildContext context) { return Stack( children: [ Positioned( child: GestureDetector( onDoubleTap: () { // 直接调用主页面的切换逻辑,无需自行处理状态和方向 onToggleOrientation(); }, child: SizedBox( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, child: InAppWebView( onReceivedServerTrustAuthRequest: (controller, challenge) async { return ServerTrustAuthResponse( action: ServerTrustAuthResponseAction.PROCEED); }, initialUrlRequest: URLRequest( url: Uri.parse('https://1stream/home/stream')), ), ), ), ), ], ); } }
补充说明
- 移除原全局
isPortrait变量,避免多页面状态冲突。 - 横屏时使用
SystemUiMode.immersiveSticky可让状态栏和导航栏自动隐藏,退出横屏时自动恢复,提升全屏观看体验。 - 若项目复杂度较高,也可使用Provider、Riverpod等状态管理库实现更灵活的跨页面状态共享。
内容的提问来源于stack exchange,提问作者user16357470
相关产品推荐
相关产品推荐

