ensureVisible method

Future<void> ensureVisible(
  1. TextSpan span, {
  2. double alignment = 0.0,
  3. Duration duration = Duration.zero,
  4. Curve curve = Curves.ease,
  5. ScrollPositionAlignmentPolicy alignmentPolicy = ScrollPositionAlignmentPolicy.explicit,
  6. double offset = 0,
  7. int spanIndex = 0,
  8. int textBoxIndex = 0,
  9. bool spanSelector(
    1. List<TextBox> spanBoxes,
    2. int index,
    3. int length
    )?,
  10. bool textBoxSelector(
    1. TextBox textBox,
    2. int index,
    3. int length
    )?,
  11. double offsetSelector(
    1. TextBox textBox,
    2. double alignment
    )?,
})

Implementation

Future<void> ensureVisible(
  TextSpan span, {
  double alignment = 0.0,
  Duration duration = Duration.zero,
  Curve curve = Curves.ease,
  ScrollPositionAlignmentPolicy alignmentPolicy =
      ScrollPositionAlignmentPolicy.explicit,
  double offset = 0,
  int spanIndex = 0,
  int textBoxIndex = 0,
  bool Function(List<TextBox> spanBoxes, int index, int length)? spanSelector,
  bool Function(TextBox textBox, int index, int length)? textBoxSelector,
  double Function(TextBox textBox, double alignment)? offsetSelector,
}) {
  var textPainter = TextPainter(
    text: widget.text,
    textDirection: widget.textDirection ?? Directionality.maybeOf(context),
    textAlign: widget.textAlign,
    textScaleFactor: widget.textScaleFactor,
    maxLines: widget.maxLines,
    ellipsis: widget.overflow == TextOverflow.ellipsis ? '\u2026' : null,
    locale: widget.locale,
    strutStyle: widget.strutStyle,
    textWidthBasis: widget.textWidthBasis,
    textHeightBehavior: widget.textHeightBehavior,
  );
  List<List<TextBox>> spanBoxesList = textPainter.getBoxesForSpan(
    span,
    maxWidth: _boxConstraints!.maxWidth,
    minWidth: _boxConstraints!.minWidth,
    minHeight: _boxConstraints!.minHeight,
    maxHeight: _boxConstraints!.maxHeight,
  );
  if (spanBoxesList.isEmpty || spanBoxesList.first.isEmpty)
    return Future.value();
  var selectedSpanBoxesIndex =
      min(max(spanIndex, 0), spanBoxesList.length - 1);
  if (spanSelector != null) {
    for (var i = 0; i < spanBoxesList.length; i++) {
      if (spanSelector(spanBoxesList[i], i, spanBoxesList.length)) {
        selectedSpanBoxesIndex = i;
        break;
      }
    }
  }
  var selectedSpanBoxes = spanBoxesList[selectedSpanBoxesIndex];
  var selectedTextBoxIndex =
      min(max(textBoxIndex, 0), selectedSpanBoxes.length - 1);
  if (textBoxSelector != null) {
    for (var i = 0; i < selectedSpanBoxes.length; i++) {
      if (textBoxSelector(
          selectedSpanBoxes[i], i, selectedSpanBoxes.length)) {
        selectedTextBoxIndex = i;
        break;
      }
    }
  }
  var selectedTextBox = selectedSpanBoxes[selectedTextBoxIndex];
  if (offsetSelector != null) {
    offset = offsetSelector(selectedTextBox, alignment);
  }
  var scrollerSize = Scrollable.of(context)?.context.size;
  return ScrollableOffset.ensureVisibleContextOffset(
    _containerKey.currentContext!,
    alignment: 0.0,
    alignmentPolicy: alignmentPolicy,
    curve: curve,
    duration: duration,
    offset: selectedTextBox.top +
        offset -
        (scrollerSize?.height ?? 0) * alignment +
        ((selectedTextBox.top - selectedTextBox.bottom) * -alignment),
  );
}