getOffsetToRevealCursor method

double? getOffsetToRevealCursor(
  1. double viewportHeight,
  2. double scrollOffset,
  3. double offsetInViewport
)

Returns the y-offset of the editor at which selection is visible.

The offset is the distance from the top of the editor and is the minimum from the current scroll position until selection becomes visible. Returns null if selection is already visible.

Finds the closest scroll offset that fully reveals the editing cursor.

The scrollOffset parameter represents current scroll offset in the parent viewport.

The offsetInViewport parameter represents the editor's vertical offset in the parent viewport. This value should normally be 0.0 if this editor is the only child of the viewport or if it's the topmost child. Otherwise it should be a positive value equal to total height of all siblings of this editor from above it.

Returns null if the cursor is currently visible.

Implementation

double? getOffsetToRevealCursor(
    double viewportHeight, double scrollOffset, double offsetInViewport) {
  // Endpoints coordinates represents lower left or lower right corner of
  // the selection. If we want to scroll up to reveal the caret we need to
  // adjust the dy value by the height of the line. We also add a small margin
  // so that the caret is not too close to the edge of the viewport.
  final endpoints = getEndpointsForSelection(selection);

  // when we drag the right handle, we should get the last point
  TextSelectionPoint endpoint;
  if (selection.isCollapsed) {
    endpoint = endpoints.first;
  } else {
    if (selection is DragTextSelection) {
      endpoint = (selection as DragTextSelection).first
          ? endpoints.first
          : endpoints.last;
    } else {
      endpoint = endpoints.first;
    }
  }

  // Collapsed selection => caret
  final child = childAtPosition(selection.extent);
  const kMargin = 8.0;

  final caretTop = endpoint.point.dy -
      child.preferredLineHeight(TextPosition(
          offset: selection.extentOffset - child.container.documentOffset)) -
      kMargin +
      offsetInViewport +
      scrollBottomInset;
  final caretBottom =
      endpoint.point.dy + kMargin + offsetInViewport + scrollBottomInset;
  double? dy;
  if (caretTop < scrollOffset) {
    dy = caretTop;
  } else if (caretBottom > scrollOffset + viewportHeight) {
    dy = caretBottom - viewportHeight;
  }
  if (dy == null) {
    return null;
  }
  // Clamping to 0.0 so that the content does not jump unnecessarily.
  return math.max(dy, 0);
}