Flutter 如何处理方向变化

How does Flutter handle orientation change

方向更改处理是否像在 Flutter 中使用更新后的尺寸重新运行小部件的构建一样简单?

我问是因为在Android中,整个Activity都被重建了,这就是为什么所有的信息都是通过intents发送的。

在设计小部件时是否需要牢记任何陷阱,以便它们能够处理方向变化或导致 UI 发生变化的其他变化?

基本上 - 是的!现在,更具体地说,MediaQuery 小部件侦听 orientation/size/layout 更改并重建它的子项。此小部件已经是 MaterialAppWidgetsApp 小部件的一部分,因此您可能不需要包含它。

如果您希望小部件利用设备方向,可以使用 MediaQuery.of 静态成员访问包含设备方向的 MediaQueryData。例如,一个以纵向和横向显示不同文本的简单小部件(需要是 MaterialAppWidgetsAppMediaQuery 的子项)。

class MyWidget extends StatelessWidget {
  Widget build(BuildContext context) {
    final mediaQueryData = MediaQuery.of(context);
    if (mediaQueryData.orientation == Orientation.landscape) {
      return const Text('landscape');
    }
    return const Text('portrait!');
  }
}

这将帮助您强制 Flutter 应用程序保持纵向(垂直)模式,即使用户正在旋转智能手机也是如此

    void main(){
  ///
  /// Force the layout to Portrait mode
  /// 
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown
  ]);

  runApp(new MyApp());
}

虽然 Jonah 上面的回答是正确的,但就我个人而言,我建议使用 switch 而不是 if

您需要在相关函数中实现不同的内容。

@override
Widget build(BuildContext context) {
  switch (MediaQuery.of(context).orientation) {
    case Orientation.landscape:
      return _landscapeContent();
    case Orientation.portrait:
    default:
      return _portraitContent();
  }
}

更新

从另一方面来说,当你有一个内部布尔值 _fullscreen 标志时,你将保持全屏状态(假设你在某处有一个全屏按钮并且想要显示该内容,即使 phone),然后if会更方便。

@override
Widget build(BuildContext context) {
  final orientation = MediaQuery.of(context).orientation;
  if (orientation == Orientation.landscape || _fullscreen) {
    return _landscapeContent();
  }
  return _portraitContent();
}

根据这个 doc 你可以使用 OrientationBuilder.

OrientationBuilder(
  builder: (context, orientation) {
    if (orientation == Orientation.portrait) 
         // return A
    else 
        // return B
});

要确定应用的当前 Orientation,请使用 OrientationBuilder 小部件。 OrientationBuilder通过比较父控件可用的宽度和高度来计算当前Orientation,并在父控件的大小发生变化时重建。

使用 Orientation,构建一个在纵向模式下显示两列或在横向模式下显示三列的列表。

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

完整示例

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    const appTitle = 'Orientation Demo';

    return const MaterialApp(
      title: appTitle,
      home: OrientationList(
        title: appTitle,
      ),
    );
  }
}

class OrientationList extends StatelessWidget {
  final String title;

  const OrientationList({Key? key, required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: OrientationBuilder(
        builder: (context, orientation) {
          return GridView.count(
            // Create a grid with 2 columns in portrait mode, or 3 columns in
            // landscape mode.
            crossAxisCount: orientation == Orientation.portrait ? 2 : 3,
            // Generate 100 widgets that display their index in the List.
            children: List.generate(100, (index) {
              return Center(
                child: Text(
                  'Item $index',
                  style: Theme.of(context).textTheme.headline1,
                ),
              );
            }),
          );
        },
      ),
    );
  }
}