【问题标题】:How to detect orientation change in layout in Flutter?如何检测 Flutter 中布局的方向变化?
【发布时间】:2018-11-21 17:22:59
【问题描述】:

如何在 Flutter 中判断方向是纵向还是横向

if(portrait){
  return ListView.builder()
}else{
  return GridView.count()
}

【问题讨论】:

    标签: dart orientation flutter flutter-layout


    【解决方案1】:

    为了确定屏幕的方向,我们可以使用OrientationBuilder Widget。 OrientationBuilder 将确定当前的 Orientation 并在 Orientation 更改时重建。

    new OrientationBuilder(
      builder: (context, orientation) {
        return new GridView.count(
          // Create a grid with 2 columns in portrait mode, or 3 columns in
          // landscape mode.
          crossAxisCount: orientation == Orientation.portrait ? 2 : 3,
        );
      },
    );
    

    您可以在此处找到完整的示例: https://flutter.io/cookbook/design/orientation/

    【讨论】:

    • 我在 Android 上使用过它,当设备的自动旋转启用时它工作正常,但大多数人使用他们的手机禁用自动旋转(强制纵向)并且 OrientationBuilder 不会触发景观。无论如何我们可以检测到关于自动旋转状态的方向吗?
    • 此选项的缺点是您可以区分方向,例如 LandscapeLeft 和 LandscapeRight。
    【解决方案2】:

    您可以使用MediaQuery 来检查方向:

    var isPortrait = MediaQuery.of(context).orientation == Orientation.portrait
    

    【讨论】:

    • @AdarshVijayanP 您不能在随机代码位置使用它。应该用在builddidChangeDependencies
    • @GünterZöchbauer 在build 中编写代码,然后传递给我的小部件,谢谢,现在效果很好。
    【解决方案3】:

    很简单

    if (MediaQuery.of(context).orientation == Orientation.portrait){
        // is portrait
    }else{
    // is landscape
    }
    

    【讨论】:

      【解决方案4】:
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: OrientationBuilder(builder: (_, orientation) {
            if (orientation == Orientation.portrait)
              return _buildPortraitLayout(); // if orientation is portrait, show your portrait layout
            else
              return _buildLandscapeLayout(); // else show the landscape one
          }),
        );
      }
      

      【讨论】:

      • OrientationBuilder 似乎只适用于脚手架级别的构建。当我构建一个有状态的小部件时,它似乎并没有在树的下方工作。我想知道这是否是已知的事情。
      【解决方案5】:
      OrientationBuilder(
      
      
       builder: (context, orientation) {
            return orientation == Orientation.portrait
                ? SafeArea(
                child: Scaffold(
                    body: PortraitMode(context)
                )
            )
                : LandscapeMode(context);
      
          }
      );
      

      【讨论】:

        【解决方案6】:

        为了完整起见,我想添加另一种在 Flutter 中检测方向的方法。答案中已经提到了两种检测方法。他们是

        1. 媒体查询
        2. 方向生成器

        当我从 Google 工程师的响应式设计video(跳到第 2:34 分钟)学习 Flutter 时,我遇到了第三种方法。它被称为Layout Builder。这是简短的sn-p:

        return Padding(
            padding: _padding,
            child: LayoutBuilder(
                builder: (BuildContext context, BoxConstraints constraints) {
                    if(constraints.maxHeight > constraints.maxWidth) {
                        return _getPortraitLayout();
                    }
                    else {
                        return _getLandscapeLayout();
                    }
                },
            ),
        );
        

        【讨论】:

        • 这仅适用于您在不受约束的布局中使用 Layout Builder(例如,在屏幕小部件树的顶部)。如果你将 LayoutBuilder 放在一个高度为 50 且宽度为 100 的容器中,你的方法将始终告诉用户他处于横向模式
        【解决方案7】:

        Mediaquery 不能在initState() 中使用,并且 OrientationBuilder 需要一个小部件,所以我创建了以下可以在项目中的任何地方使用的类。

        if(IsPortrait.isPortrait){
        }else{
        }
        

        IsPortrait.class

        class IsPortrait{
          static bool isPortrait = true;
        
          void init(BoxConstraints constraints, Orientation orientation) {
            if (orientation == Orientation.portrait) {
              isPortrait = true;
            }
           else{
             isPortrait = false;
           }
          }
        }
        

        以下功能可用于改变方向

        仅纵向模式

        /// blocks rotation; sets orientation to: portrait
        void _portraitModeOnly() {
          SystemChrome.setPreferredOrientations([
            DeviceOrientation.portraitUp,
            DeviceOrientation.portraitDown,
          ]);
        }
        

        仅限横向模式

        /// blocks rotation; sets orientation to: landscape
            void _landscapeModeOnly() {
              SystemChrome.setPreferredOrientations([
            DeviceOrientation.landscapeLeft,
            DeviceOrientation.landscapeRight,
              ]);
            }
        

        启用纵向和横向

        void _enableRotation() {
          SystemChrome.setPreferredOrientations([
            DeviceOrientation.portraitUp,
            DeviceOrientation.portraitDown,
            DeviceOrientation.landscapeLeft,
            DeviceOrientation.landscapeRight,
          ]);
        }
        

        【讨论】:

          【解决方案8】:

          我的变种。

          1) 在全局范围内设置全局 ValueNotifier:

          final ValueNotifier<bool> IS_PORTRAIT = ValueNotifier<bool>(true);
          

          2) 在我们的全局 ValueNotifier 的脚手架范围内更改值

          return Scaffold(
                  key: scaffoldKey,
                  body: OrientationBuilder(
                    builder: (BuildContext context, Orientation orientation) {
                      IS_PORTRAIT.value = orientation == Orientation.portrait;
                      return MyBody();
                    },
                  ),
          );
          

          3) 听当前方向的任何地方

          return ValueListenableBuilder(
                            valueListenable: IS_PORTRAIT,
                            builder: (BuildContext context, value, Widget child) {
                               return Container(
                                color: Colors.green[100],
                                child: Container(),
                                height: (IS_PORTRAIT.value)? 150: 80,
                              );
                            },
                          );
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-18
            • 2019-08-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多