如何检测 Flutter 中布局的方向变化?
Posted
技术标签:
【中文标题】如何检测 Flutter 中布局的方向变化?【英文标题】:How to detect orientation change in layout in Flutter? 【发布时间】:2018-11-21 17:22:59 【问题描述】:如何在 Flutter 中判断方向是纵向还是横向
if(portrait)
return ListView.builder()
else
return GridView.count()
【问题讨论】:
【参考方案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 不会触发景观。无论如何我们可以检测到关于自动旋转状态的方向吗? 你觉得github.com/flutter/flutter/issues/19259怎么样? 此选项的缺点是您可以区分方向,例如 LandscapeLeft 和 LandscapeRight。【参考方案2】:您可以使用MediaQuery
来检查方向:
var isPortrait = MediaQuery.of(context).orientation == Orientation.portrait
【讨论】:
@AdarshVijayanP 您不能在随机代码位置使用它。应该用在build
或didChangeDependencies
@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 中检测方向的方法。答案中已经提到了两种检测方法。他们是
-
媒体查询
方向生成器
当我从 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,
);
,
);
【讨论】:
以上是关于如何检测 Flutter 中布局的方向变化?的主要内容,如果未能解决你的问题,请参考以下文章