如何检测 Flutter 中布局的方向变化?

How to detect orientation change in layout in Flutter?

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

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

您可以使用 MediaQuery 检查方向:

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

为了确定屏幕的方向,我们可以使用 OrientationBuilder 小部件。 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/

很简单

if (MediaQuery.of(context).orientation == Orientation.portrait){
    // is portrait
}else{
// is landscape
}
@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(


 builder: (context, orientation) {
      return orientation == Orientation.portrait
          ? SafeArea(
          child: Scaffold(
              body: PortraitMode(context)
          )
      )
          : LandscapeMode(context);

    }
);

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

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

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

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

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

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,
  ]);
}

我的变体。

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) Any where listen current orientation

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,
                    );
                  },
                );