getOffsetToRevealCursor method

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

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) {
  const kMargin = 8.0;
  // 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);
  final targetEndpoint = endpoints.length == 1
      ? endpoints.single
      : selection.affinity == TextAffinity.downstream
          ? endpoints.first
          : endpoints.last;
  // if (endpoints.length == 1) {
  // Collapsed selection => caret
  final child = childAtPosition(selection.extent);
  final childPosition =
      TextPosition(offset: selection.extentOffset - child.node.offset);
  final caretTop = targetEndpoint.point.dy -
      child.preferredLineHeight(childPosition) -
      kMargin +
      offsetInViewport;
  final caretBottom = targetEndpoint.point.dy + kMargin + offsetInViewport;
  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.0);
  // }
  // TODO: Implement for non-collapsed selection.
  // return null;
}