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 spanSelector(
- List<TextBox> spanBoxes,
- int index,
- int length
)?,
- bool textBoxSelector(
- TextBox textBox,
- int index,
- int length
)?,
- double offsetSelector(
- TextBox textBox,
- 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),
);
}