The Paragraph class in Flutter has a method called getBoxesForRange
.
The documentation says:
Returns a list of text boxes that enclose the given text range.
However, it's not clear to me if the boxes are the boxes around the lines of text that include the given range or if they are something else.
After doing further research, I found an answer, which I'm adding below.
Paragraph.getBoxesForRange
gives you what would essentially be the highlighted area for the given range if it were selected. You get more than one box if the range wraps to a new line (or if it contains mixed bi-directional text).
Given the string:
Hello, world.
If you take the range from 1
to 8
like so:
final boxes = paragraph.getBoxesForRange(1, 8);
This will give you a single box:
[
TextBox.fromLTRBD(22.3, -0.3, 112.0, 35.0, TextDirection.ltr)
]
Graphically represented it would look like this:
This shows that the boxes are not full lines but only wrap the specified text range.
If you restrict the width so that the paragraph is forced to line wrap the text, you get the following:
[
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)
]
Here is the full code if you want to play around with it yourself.
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;
}
}