paint method

  1. @override
void paint(
  1. PaintingContext context,
  2. Offset offset
)
override

Paint this render object into the given context at the given offset.

Subclasses should override this method to provide a visual appearance for themselves. The render object's local coordinate system is axis-aligned with the coordinate system of the context's canvas and the render object's local origin (i.e, x=0 and y=0) is placed at the given offset in the context's canvas.

Do not call this function directly. If you wish to paint yourself, call markNeedsPaint instead to schedule a call to this function. If you wish to paint one of your children, call PaintingContext.paintChild on the given context.

When painting one of your children (via a paint child function on the given context), the current canvas held by the context might change because draw operations before and after painting children might need to be recorded on separate compositing layers.

Implementation

@override
void paint(PaintingContext context, Offset offset) {
  if (firstChild == null) {
    return;
  }

  RenderBox? nextChild = firstChild;
  void paintUpTo(
    int index,
    RenderBox? startWith,
    PaintingContext context,
    Offset offset,
  ) {
    RenderBox? child = startWith;
    while (child != null && indexOf(child) <= index) {
      final double mainAxisDelta = childMainAxisPosition(child);
      final TreeSliverNodeParentData parentData = child.parentData! as TreeSliverNodeParentData;
      final Offset childOffset = Offset(
        parentData.depth * indentation,
        parentData.layoutOffset!,
      );

      // If the child's visible interval (mainAxisDelta, mainAxisDelta + paintExtentOf(child))
      // does not intersect the paint extent interval (0, constraints.remainingPaintExtent), it's hidden.
      if (mainAxisDelta < constraints.remainingPaintExtent && mainAxisDelta + paintExtentOf(child) > 0) {
        context.paintChild(child, childOffset);
      }
      child = childAfter(child);
    }
    nextChild = child;
  }
  if (_animationLeadingIndices.isEmpty) {
    // There are no animations running.
    paintUpTo(indexOf(lastChild!), firstChild, context, offset);
    return;
  }

  // We are animating.
  // Separate animating segments to clip for any overlap.
  int leadingIndex = indexOf(firstChild!);
  final List<int> animationIndices = _animationLeadingIndices.keys.toList()..sort();
  final List<_PaintSegment> paintSegments = <_PaintSegment>[];
  while (animationIndices.isNotEmpty) {
    final int trailingIndex = animationIndices.removeAt(0);
    paintSegments.add((leadingIndex: leadingIndex, trailingIndex: trailingIndex));
    leadingIndex = trailingIndex + 1;
  }
  paintSegments.add((leadingIndex: leadingIndex, trailingIndex: indexOf(lastChild!)));

  // Paint, clipping for all but the first segment.
  paintUpTo(paintSegments.removeAt(0).trailingIndex, nextChild, context, offset);
  // Paint the rest with clip layers.
  while (paintSegments.isNotEmpty) {
    final _PaintSegment segment = paintSegments.removeAt(0);

    // Rect is calculated by the trailing edge of the parent (preceding
    // leadingIndex), and the trailing edge of the trailing index. We cannot
    // rely on the leading edge of the leading index, because it is currently
    // moving.
    final int parentIndex = math.max(segment.leadingIndex - 1, 0);
    final double leadingOffset = indexToLayoutOffset(0.0, parentIndex)
      + (parentIndex == 0 ? 0.0 : itemExtentBuilder(parentIndex, _currentLayoutDimensions)!);
    final double trailingOffset = indexToLayoutOffset(0.0, segment.trailingIndex)
      + itemExtentBuilder(segment.trailingIndex, _currentLayoutDimensions)!;
    final Rect rect = Rect.fromPoints(
      Offset(0.0, leadingOffset),
      Offset(constraints.crossAxisExtent, trailingOffset),
    );
    // We use the same animation key to keep track of the clip layer, unless
    // this is the odd man out segment.
    final UniqueKey key = _animationLeadingIndices[parentIndex]!;
    _clipHandles[key] ??=  LayerHandle<ClipRectLayer>();
    _clipHandles[key]!.layer = context.pushClipRect(
      needsCompositing,
      offset,
      rect,
      (PaintingContext context, Offset offset) {
        paintUpTo(segment.trailingIndex, nextChild, context, offset);
      },
      oldLayer: _clipHandles[key]!.layer,
    );
  }
}