Класс Paragraph во Flutter имеет метод под названием getBoxesForRange.
В документации говорится:
Возвращает список текстовых полей, которые заключают в себе заданный текстовый диапазон.
Однако мне не ясно, являются ли поля рамками вокруг строк текста, которые включают заданный диапазон, или это что-то еще.
Проведя дальнейшие исследования, я нашел ответ, который добавляю ниже.





Paragraph.getBoxesForRange дает вам то, что по существу было бы выделенной областью для данного диапазона, если бы он был выбран. Вы получаете более одного поля, если диапазон переносится на новую строку (или если он содержит смешанный двунаправленный текст).
Учитывая строку:
Hello, world.
Если вы возьмете диапазон от 1 до 8 так:
final boxes = paragraph.getBoxesForRange(1, 8);
Это даст вам одну коробку:
[
TextBox.fromLTRBD(22.3, -0.3, 112.0, 35.0, TextDirection.ltr)
]
Графически это будет выглядеть так:
Это показывает, что поля не являются полными строками, а только оборачивают указанный диапазон текста.
Если вы ограничите ширину так, чтобы абзац был вынужден переносить текст, вы получите следующее:
[
TextBox.fromLTRBD(22.3, -0.3, 47.0, 35.0, TextDirection.ltr),
TextBox.fromLTRBD(0.0, 34.7, 41.8, 70.0, TextDirection.ltr),
TextBox.fromLTRBD(0.0, 69.7, 23.2, 105.0, TextDirection.ltr)
]
Вот полный код, если вы хотите поиграть с ним самостоятельно.
import 'package:flutter/material.dart';
import 'dart:ui' as ui;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: HomeWidget(),
),
);
}
}
class HomeWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: CustomPaint(
size: Size(300, 300),
painter: MyPainter(),
),
);
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final textStyle = ui.TextStyle(
color: Colors.black,
fontSize: 30,
);
final paragraphStyle = ui.ParagraphStyle(
textDirection: TextDirection.ltr,
);
final paragraphBuilder = ui.ParagraphBuilder(paragraphStyle)
..pushStyle(textStyle)
..addText('Hello, world.');
final constraints = ui.ParagraphConstraints(width: 300);
// final constraints = ui.ParagraphConstraints(width: 50);
final paragraph = paragraphBuilder.build();
paragraph.layout(constraints);
canvas.drawParagraph(paragraph, Offset.zero);
final boxes = paragraph.getBoxesForRange(1, 8);
print(boxes);
final paint = Paint()
..color = Colors.blue
..style = PaintingStyle.stroke
..strokeWidth = 1;
for (final box in boxes) {
final rect = Rect.fromLTRB(box.left, box.top, box.right, box.bottom);
canvas.drawRect(rect, paint);
}
}
@override
bool shouldRepaint(CustomPainter old) {
return false;
}
}