OrientationBuilder
报告完全转换后的方向变化,然后在此之后进行重建。
在入职培训之前,有没有办法采取行动?我不是要抢先轮换,而是要同时进行更改,而不是在此之后进行更改。
目标:
挑战,如何在3出现之前实现点2?
答案 0 :(得分:8)
是的,您可以使用WidgetsBindingObserver
通过覆盖didChangeMetrics
来更早获得方向更改。
didChangeMetrics
您可以简单地在有状态的小部件的State
implementation中混入WidgetBindingObserver
:
class _FooState extends State with WidgetsBindingObserver {
@override
void didChangeMetrics() {
// This will be triggered by changes in orientation.
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
}
方向由可用尺寸的长宽比确定。这意味着您可以使用以下代码在didChangeMetrics
中获得方向:
final orientation = WidgetsBinding.instance.window.physicalSize
.aspectRatio > 1 ? Orientation.landscape : Orientation.portrait;
我构建了一个示例StatefulWidget
,将OrientationBuilder
回调与didChangeMetrics
进行了比较:
import 'package:flutter/material.dart';
void main() {
runApp(OrientationListener());
}
class OrientationListener extends StatefulWidget {
@override
_OrientationListenerState createState() => _OrientationListenerState();
}
class _OrientationListenerState extends State<OrientationListener>
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeMetrics() {
print('$WidgetsBindingObserver metrics changed ${DateTime.now()}: '
'${WidgetsBinding.instance.window.physicalSize.aspectRatio > 1 ? Orientation.landscape : Orientation.portrait}');
}
@override
Widget build(BuildContext context) {
return MediaQuery(
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window),
child: OrientationBuilder(
builder: (context, orientation) {
print('$OrientationBuilder rebuild ${DateTime.now()}: $orientation');
return Container();
},
),
);
}
}
运行此示例将显示以下两个功能的时间:
WidgetsBindingObserver metrics changed 2020-08-22 14:47:01.690172: Orientation.portrait
WidgetsBindingObserver metrics changed 2020-08-22 14:47:01.706574: Orientation.landscape
OrientationBuilder rebuild 2020-08-22 14:47:01.760589: Orientation.landscape
WidgetsBindingObserver metrics changed 2020-08-22 14:47:06.537083: Orientation.landscape
WidgetsBindingObserver metrics changed 2020-08-22 14:47:06.549545: Orientation.portrait
OrientationBuilder rebuild 2020-08-22 14:47:06.603859: Orientation.portrait
WidgetsBindingObserver metrics changed 2020-08-22 14:47:10.423787: Orientation.portrait
WidgetsBindingObserver metrics changed 2020-08-22 14:47:10.442866: Orientation.landscape
OrientationBuilder rebuild 2020-08-22 14:47:10.501729: Orientation.landscape
WidgetsBindingObserver metrics changed 2020-08-22 14:47:13.639545: Orientation.landscape
WidgetsBindingObserver metrics changed 2020-08-22 14:47:13.658906: Orientation.landscape
WidgetsBindingObserver metrics changed 2020-08-22 14:47:13.672025: Orientation.portrait
OrientationBuilder rebuild 2020-08-22 14:47:13.730771: Orientation.portrait
因此,在我的情况下,检测差异大约为0.06
秒。
从上面可以看到,差异不明显(我会说)。因此,我什至不确定这是否对您有用。
此外,我观察到OrientationBuilder
回调实际上是在设备旋转开始时被称为 的-至少在我的Android仿真器上。这意味着您可以在轮换发生之前重建UI。
我希望这对您有所帮助:)
答案 1 :(得分:4)
正如您在此链接中看到的那样,没有“自然”的方式来做您想要的事情:
https://github.com/flutter/flutter/issues/16322
尝试使用以下方法制作东西:
您可以尝试使用动画容器以获得更好的效果,但是在设置新方向之前,您需要手动处理所有屏幕位置和旋转:
https://api.flutter.dev/flutter/widgets/AnimatedContainer-class.html
答案 2 :(得分:0)
您可能想尝试的事情是编写一个平台通道方法,以从加速度计获取传感器数据,然后将其提供给Transform.rotate()之类的东西。