OrientationBuilder在完全转换后报告方向更改,然后在此之后进行重建。
在定向开始之前,有没有办法采取行动?我不是要抢先轮换,而是要同时进行更改,而不是在此之后进行更改。
目标:

  • 设备已旋转。
  • 检测到此并重建UI以显示覆盖。
  • Flutter执行自己的转换,将UI旋转到新的方向。
  • 在固定时间段后,只需重建即可隐藏覆盖。

  • 挑战,如何在3发生之前实现点2?

    最佳答案

    是的,您可以通过覆盖 WidgetsBindingObserver 来使用didChangeMetrics来获取方向更改早于
    如何使用didChangeMetrics您可以简单地在有状态的小部件的 WidgetBindingObserver implementation中混合State:

    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。

    我希望这对您有帮助:)

    08-16 16:30