我正在寻找一种监听手机方向变化的方法,以便在手机处于横屏状态时隐藏某些内容。
我的布局目前仅以纵向显示,这是我的本意,但我希望当设备旋转到横向时,我的应用程序可以做一些事情,同时保持布局为纵向。
我尝试使用OrientationBuilder
,但这只在布局更改为横向时起作用。
我也尝试使用MediaQuery.of(context).orientation
,但它继续返回纵向,一旦设备旋转,仍然只使用布局的方向。
我正在寻找一种监听手机方向变化的方法,以便在手机处于横屏状态时隐藏某些内容。
我的布局目前仅以纵向显示,这是我的本意,但我希望当设备旋转到横向时,我的应用程序可以做一些事情,同时保持布局为纵向。
我尝试使用OrientationBuilder
,但这只在布局更改为横向时起作用。
我也尝试使用MediaQuery.of(context).orientation
,但它继续返回纵向,一旦设备旋转,仍然只使用布局的方向。
您可以监听屏幕尺寸的变化,但MediaQuery.of(...)
也应该起作用,并且在方向更改时应导致小部件重建。
https://stephenmann.io/post/listening-to-device-rotations-in-flutter/
import 'dart:ui';
import 'package:flutter/material.dart';
class WidthHeight extends StatefulWidget {
WidthHeight({ Key key }) : super(key: key);
@override
WidthHeightState createState() => new WidthHeightState();
}
class WidthHeightState extends State
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
double width = 0.0;
double height = 0.0;
@override void didChangeMetrics() {
setState(() {
width = window.physicalSize.width;
height = window.physicalSize.height;
});
}
@override
Widget build(BuildContext context) {
return new Text('Width: $width, Height $height');
}
}
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
,仍然希望在屏幕旋转时接收回调。 - Jonasfinal orientation =
WidgetsBinding.instance.window.physicalSize.aspectRatio > 1
? Orientation.landscape
: Orientation.portrait;
if (_currentOrientation != orientation) {
// Do stuff
_currentOrientation = orientation;
}
- whidev在didChangeMetrics()中直接使用MediaQuery会返回之前的值。要在方向更改后获得最新值,请在里面使用WidgetsBinding.instance.addPostFrameCallback()。
https://github.com/flutter/flutter/issues/60899class OrientationSample extends StatefulWidget {
const OrientationSample({Key? key}) : super(key: key);
@override
_OrientationSampleState createState() => _OrientationSampleState();
}
class _OrientationSampleState extends State<OrientationSample> with WidgetsBindingObserver {
Orientation? _currentOrientation;
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance?.removeObserver(this);
super.dispose();
}
@override
void didChangeMetrics() {
_currentOrientation = MediaQuery.of(context).orientation;
print('Before Orientation Change: $_currentOrientation');
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
setState(() {
_currentOrientation = MediaQuery.of(context).orientation;
});
print('After Orientation Change: $_currentOrientation');
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: _currentOrientation != null ? Text('$_currentOrientation') : Text('Rotate Device to Test'),
),
);
}
}
您可以使用可见性来包装小部件,并设置不透明度参数为getOpacityForOrientation(),在您的屏幕中,您可以添加以下函数:
double getOpacityForOrientation() {
if (MediaQuery.of(context).orientation == Orientation.landscape) {
return 0;
} else {
return 1;
}
}
OrientationBuilder
还是MediaQuery.of(context).orientation
都可以完成任务。但是您说设备的方向从未更改,这使我想到您尚未在设备上启用自动旋转。
您能否从快速设置中启用自动旋转并进行尝试?
OrientationBuilder
只是告诉你父部件是否比高度更宽(或反之),与设备的方向无关。这是一个常见的误解,可能是因为名称不够理想。 - Günter ZöchbauerOrientationBuilder
给我们的是父部件的方向,而不是设备的方向。除非父部件是水平布局,否则它们大多数情况下是相同的。但是,这里的 OP 似乎并没有遇到这个问题,因为他也尝试了 MediaQuery
。我的答案的关键是“启用自动旋转”。 - Amsakannaorientation_provider.dart
import 'package:flutter/material.dart';
class OrientationProvider extends ChangeNotifier {
Orientation _orientation = Orientation.portrait;
Orientation get getOrientation {
return _orientation;
}
void changeOrientation(Orientation newOrientation) {
print("CHANGE ORIENTATION CALLED: old: $_orientation, new: $newOrientation");
bool hasChanged = _orientation != newOrientation;
_orientation = newOrientation;
if(hasChanged) notifyListeners();
}
}
.
.
.
child: OrientationBuilder(
builder: (context, orientation){
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
context.read<OrientationProvider>().changeOrientation(orientation);
});
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.dark().copyWith(
textTheme: ThemeData.dark().textTheme.apply(
fontFamily: 'Nunito',
),
.
.
.
需要监听屏幕方向变化的位置
child: context.watch<OrientationProvider>().getOrientation == Orientation.portrait ? WIDGET_PORTRAIT
: WIDGET_LANDSCAPE
我在这里发布这篇文章,试图帮助一点,但是我要诚实地说,它感觉像一个hack。Matthew所描述的问题是--如果你在编译时特别锁定你的应用程序为竖屏模式,MediaQuery和OrientationBuilder都没有帮助,因为它们从未被触发。在我的情况下,我有一个应用程序被锁定为竖屏,但我正在尝试添加一个屏幕来流视频,我希望当手机旋转时可以全屏播放。如上所述,由于它在编译时被锁定,MediaQuery和OrientationBuilder将不起作用。
对于我的屏幕控制器中的“hack”,我监听加速度计事件API的流订阅。如果流事件.y是< 3,则手机接近水平,我可以使用它来更改控制承载视频播放器的扩展旋转框的旋转次数的int。
这不能解决右手或左手旋转的问题...就像我说的,它感觉像一个hack,但这是一个开始...
如果你想要检测设备的方向,只需使用类似以下的代码
String type_orien = "potrait";
Future<void> detect_change_orientation() async {
await Future.delayed(const Duration(seconds: 1), () async {
if (MediaQuery.of(context).orientation == Orientation.landscape) {
if (type_orien ==
"potrait") // if orien change and before is potrait then reload again
{
print("landscape ss");
await reload_set_scren();
type_orien = "landscape";
}
} else {
if (type_orien ==
"landscape") // if orien change and before is landscape then reload again
{
print("potrait ss");
await reload_set_scren();
type_orien = "potrait";
}
}
});
}
Future<void> reload_set_scren() {
//... do whats ever u want
}
@override
Widget build(BuildContext context) {
detect_change_orientation(); // call function here <--
return Scaffold(
);
}