关于更改主题的关闭打开的对话框和选项菜单中的问题

问题描述 投票:0回答:1

我一直在从事一个项目,该项目需要我根据移动设备的orientation更改屏幕小部件。

例如,

portrait方向的情况下,我需要显示一个小部件(假设是纵向小部件),在landscape方向的情况下,我需要显示另一个小部件(将其称为横向小部件)。

我用过OrientationBuilder

实际问题:更改方向时,不会关闭所有DialogsOptionMenu或任何其他Popup类型的小部件。如何在方向改变时关闭它们?

重现问题的步骤:

  1. 运行下面提供的应用程序代码[用于再现问题的示例应用程序]
  2. 长按应用程序主体以查看对话框或单击左上角的OptionMenu
  3. 更改设备方向,您会看到小部件主体已根据方向进行了更改,但Popuped小部件仍然可见。

示例应用代码:

// main.dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return OrientationBuilder(builder: (context, orientation) {
      bool isLandscape = orientation == Orientation.landscape;
      return isLandscape ? Landscape() : Portrait();
    });
  }
}

class Portrait extends StatefulWidget {
  @override
  _PortraitState createState() => _PortraitState();
}

class _PortraitState extends State<Portrait> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: buildTitle(),
        actions: <Widget>[_buildOptionMenu(context)],
      ),
      body: GestureDetector(
        onLongPress: () {
          showDialog(
            context: context,
            builder: (context) => AlertDialog(
              content: buildTitle(),
            ),
          );
        },
        child: Container(
          color: Colors.blue.withOpacity(0.4),
          child: Stack(
            fit: StackFit.expand,
            children: <Widget>[
              Center(
                child: buildTitle(),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildOptionMenu(BuildContext context) {
    return PopupMenuButton(itemBuilder: (context) {
      var list = <String>['Portrait-Item-1', 'Portrait-Item-2'];
      return list
          .map<PopupMenuEntry<String>>(
            (e) => PopupMenuItem<String>(
              child: Text(e),
            ),
          )
          .toList();
    });
  }

  Text buildTitle() => Text('Portrait');
}

class Landscape extends StatefulWidget {
  @override
  _LandscapeState createState() => _LandscapeState();
}

class _LandscapeState extends State<Landscape> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: buildTitle(),
        actions: <Widget>[_buildOptionMenu(context)],
      ),
      body: GestureDetector(
        onLongPress: () {
          showDialog(
            context: context,
            builder: (context) => AlertDialog(
              content: buildTitle(),
            ),
          );
        },
        child: Container(
          color: Colors.orange.withOpacity(0.3),
          child: Stack(
            fit: StackFit.expand,
            children: <Widget>[
              Center(
                child: buildTitle(),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Text buildTitle() => Text('Landscape');

  Widget _buildOptionMenu(BuildContext context) {
    return PopupMenuButton(itemBuilder: (context) {
      var list = <String>[
        'Landscape-Item-1',
        'Landscape-Item-2',
        'Landscape-Item-3',
      ];
      return list
          .map<PopupMenuEntry<String>>(
            (e) => PopupMenuItem<String>(
              child: Text(e),
            ),
          )
          .toList();
    });
  }
}

我找不到任何可行的解决方案。有一些解决方案需要侦听方向更改以及基于新方向的推送/弹出窗口小部件。

但是要使用太多的代码,需要在纵向和横向小部件中添加相同类型的代码。如果我需要处理其他方向(例如反向肖像和反向风景),这也是不可扩展的。

感谢您的帮助。如果您认为缺少某些内容,请在评论中通知我,我将尽快更新所需的详细信息。

提前感谢。

flutter screen-orientation
1个回答
0
投票

作为选项

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return OrientationBuilder(builder: (context, orientation) {
      bool isLandscape = orientation == Orientation.landscape;
      Navigator.of(context).popUntil(ModalRoute.withName('/')); // add this line
      return isLandscape ? Landscape() : Portrait();
    });
  }
}

当您添加导航时,只需将根路径名称'/'更改为您的路径名称

© www.soinside.com 2019 - 2024. All rights reserved.