size property Null safety

Size? size
override

The size of the RenderBox returned by findRenderObject.

This getter will only return a valid result after the layout phase is complete. It is therefore not valid to call this from a build method. It should only be called from paint callbacks or interaction event handlers (e.g. gesture callbacks).

For details on the different phases of a frame, see the discussion at WidgetsBinding.drawFrame.

This getter will only return a valid result if findRenderObject actually returns a RenderBox. If findRenderObject returns a render object that is not a subtype of RenderBox (e.g., RenderView), this getter will throw an exception in debug mode and will return null in release mode.

Calling this getter is theoretically relatively expensive (O(N) in the depth of the tree), but in practice is usually cheap because the tree usually has many render objects and therefore the distance to the nearest render object is usually short.

Implementation

@override
Size? get size {
  assert(() {
    if (_lifecycleState != _ElementLifecycle.active) {
      // TODO(jacobr): is this a good separation into contract and violation?
      // I have added a line of white space.
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('Cannot get size of inactive element.'),
        ErrorDescription(
          'In order for an element to have a valid size, the element must be '
          'active, which means it is part of the tree.\n'
          'Instead, this element is in the $_lifecycleState state.',
        ),
        describeElement('The size getter was called for the following element'),
      ]);
    }
    if (owner!._debugBuilding) {
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('Cannot get size during build.'),
        ErrorDescription(
          'The size of this render object has not yet been determined because '
          'the framework is still in the process of building widgets, which '
          'means the render tree for this frame has not yet been determined. '
          'The size getter should only be called from paint callbacks or '
          'interaction event handlers (e.g. gesture callbacks).',
        ),
        ErrorSpacer(),
        ErrorHint(
          'If you need some sizing information during build to decide which '
          'widgets to build, consider using a LayoutBuilder widget, which can '
          'tell you the layout constraints at a given location in the tree. See '
          '<https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html> '
          'for more details.',
        ),
        ErrorSpacer(),
        describeElement('The size getter was called for the following element'),
      ]);
    }
    return true;
  }());
  final RenderObject? renderObject = findRenderObject();
  assert(() {
    if (renderObject == null) {
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('Cannot get size without a render object.'),
        ErrorHint(
          'In order for an element to have a valid size, the element must have '
          'an associated render object. This element does not have an associated '
          'render object, which typically means that the size getter was called '
          'too early in the pipeline (e.g., during the build phase) before the '
          'framework has created the render tree.',
        ),
        describeElement('The size getter was called for the following element'),
      ]);
    }
    if (renderObject is RenderSliver) {
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('Cannot get size from a RenderSliver.'),
        ErrorHint(
          'The render object associated with this element is a '
          '${renderObject.runtimeType}, which is a subtype of RenderSliver. '
          'Slivers do not have a size per se. They have a more elaborate '
          'geometry description, which can be accessed by calling '
          'findRenderObject and then using the "geometry" getter on the '
          'resulting object.',
        ),
        describeElement('The size getter was called for the following element'),
        renderObject.describeForError('The associated render sliver was'),
      ]);
    }
    if (renderObject is! RenderBox) {
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('Cannot get size from a render object that is not a RenderBox.'),
        ErrorHint(
          'Instead of being a subtype of RenderBox, the render object associated '
          'with this element is a ${renderObject.runtimeType}. If this type of '
          'render object does have a size, consider calling findRenderObject '
          'and extracting its size manually.',
        ),
        describeElement('The size getter was called for the following element'),
        renderObject.describeForError('The associated render object was'),
      ]);
    }
    final RenderBox box = renderObject;
    if (!box.hasSize) {
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('Cannot get size from a render object that has not been through layout.'),
        ErrorHint(
          'The size of this render object has not yet been determined because '
          'this render object has not yet been through layout, which typically '
          'means that the size getter was called too early in the pipeline '
          '(e.g., during the build phase) before the framework has determined '
          'the size and position of the render objects during layout.',
        ),
        describeElement('The size getter was called for the following element'),
        box.describeForError('The render object from which the size was to be obtained was'),
      ]);
    }
    if (box.debugNeedsLayout) {
      throw FlutterError.fromParts(<DiagnosticsNode>[
        ErrorSummary('Cannot get size from a render object that has been marked dirty for layout.'),
        ErrorHint(
          'The size of this render object is ambiguous because this render object has '
          'been modified since it was last laid out, which typically means that the size '
          'getter was called too early in the pipeline (e.g., during the build phase) '
          'before the framework has determined the size and position of the render '
          'objects during layout.',
        ),
        describeElement('The size getter was called for the following element'),
        box.describeForError('The render object from which the size was to be obtained was'),
        ErrorHint(
          'Consider using debugPrintMarkNeedsLayoutStacks to determine why the render '
          'object in question is dirty, if you did not expect this.',
        ),
      ]);
    }
    return true;
  }());
  if (renderObject is RenderBox) {
    return renderObject.size;
  }
  return null;
}