didChangeMetrics method Null safety

  1. @override
void didChangeMetrics()
override

Called when the application's dimensions change. For example, when a phone is rotated.

This method exposes notifications from dart:ui.PlatformDispatcher.onMetricsChanged.

This StatefulWidget implements the parts of the State and WidgetsBindingObserver protocols necessary to react when the device is rotated (or otherwise changes dimensions).
class MetricsReactor extends StatefulWidget {
  const MetricsReactor({ super.key });

  @override
  State<MetricsReactor> createState() => _MetricsReactorState();
}

class _MetricsReactorState extends State<MetricsReactor> with WidgetsBindingObserver {
  late Size _lastSize;

  @override
  void initState() {
    super.initState();
    _lastSize = WidgetsBinding.instance.window.physicalSize;
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeMetrics() {
    setState(() { _lastSize = WidgetsBinding.instance.window.physicalSize; });
  }

  @override
  Widget build(BuildContext context) {
    return Text('Current size: $_lastSize');
  }
}

In general, this is unnecessary as the layout system takes care of automatically recomputing the application geometry when the application size changes.

See also:

  • MediaQuery.of, which provides a similar service with less boilerplate.

Implementation

@override
void didChangeMetrics() {
  if (_lastBottomViewInset != WidgetsBinding.instance.window.viewInsets.bottom) {
    SchedulerBinding.instance.addPostFrameCallback((Duration _) {
      _selectionOverlay?.updateForScroll();
    });
    if (_lastBottomViewInset < WidgetsBinding.instance.window.viewInsets.bottom) {
      // Because the metrics change signal from engine will come here every frame
      // (on both iOS and Android). So we don't need to show caret with animation.
      _scheduleShowCaretOnScreen(withAnimation: false);
    }
  }
  _lastBottomViewInset = WidgetsBinding.instance.window.viewInsets.bottom;
}