Utility methods for measuring text (#111493)

This commit is contained in:
Dan Field 2022-09-13 12:47:26 -07:00 committed by GitHub
parent 7b5241b39b
commit 07c1ef25a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 11 deletions

View file

@ -470,23 +470,13 @@ class CupertinoDatePicker extends StatefulWidget {
assert(longestText != '', 'column type is not appropriate');
final TextPainter painter = TextPainter(
return TextPainter.computeMaxIntrinsicWidth(
text: TextSpan(
style: _themeTextStyle(context),
text: longestText,
),
textDirection: Directionality.of(context),
);
// This operation is expensive and should be avoided. It is called here only
// because there's no other way to get the information we want without
// laying out the text.
painter.layout();
try {
return painter.maxIntrinsicWidth;
} finally {
painter.dispose();
}
}
}

View file

@ -217,6 +217,86 @@ class TextPainter {
_textWidthBasis = textWidthBasis,
_textHeightBehavior = textHeightBehavior;
/// Computes the width of a configured [TextPainter].
///
/// This is a convenience method that creates a text painter with the supplied
/// parameters, lays it out with the supplied [minWidth] and [maxWidth], and
/// returns its [TextPainter.width] making sure to dispose the underlying
/// resources.
static double computeWidth({
required InlineSpan text,
TextAlign textAlign = TextAlign.start,
TextDirection? textDirection,
double textScaleFactor = 1.0,
int? maxLines,
String? ellipsis,
Locale? locale,
StrutStyle? strutStyle,
TextWidthBasis textWidthBasis = TextWidthBasis.parent,
ui.TextHeightBehavior? textHeightBehavior,
double minWidth = 0.0,
double maxWidth = double.infinity,
}) {
final TextPainter painter = TextPainter(
text: text,
textAlign: textAlign,
textDirection: textDirection,
textScaleFactor: textScaleFactor,
maxLines: maxLines,
ellipsis: ellipsis,
locale: locale,
strutStyle: strutStyle,
textWidthBasis: textWidthBasis,
textHeightBehavior: textHeightBehavior,
)..layout(minWidth: minWidth, maxWidth: maxWidth);
try {
return painter.width;
} finally {
painter.dispose();
}
}
/// Computes the max intrinsic width of a configured [TextPainter].
///
/// This is a convenience method that creates a text painter with the supplied
/// parameters, lays it out with the supplied [minWidth] and [maxWidth], and
/// returns its [TextPainter.maxIntrinsicWidth] making sure to dispose the
/// underlying resources.
static double computeMaxIntrinsicWidth({
required InlineSpan text,
TextAlign textAlign = TextAlign.start,
TextDirection? textDirection,
double textScaleFactor = 1.0,
int? maxLines,
String? ellipsis,
Locale? locale,
StrutStyle? strutStyle,
TextWidthBasis textWidthBasis = TextWidthBasis.parent,
ui.TextHeightBehavior? textHeightBehavior,
double minWidth = 0.0,
double maxWidth = double.infinity,
}) {
final TextPainter painter = TextPainter(
text: text,
textAlign: textAlign,
textDirection: textDirection,
textScaleFactor: textScaleFactor,
maxLines: maxLines,
ellipsis: ellipsis,
locale: locale,
strutStyle: strutStyle,
textWidthBasis: textWidthBasis,
textHeightBehavior: textHeightBehavior,
)..layout(minWidth: minWidth, maxWidth: maxWidth);
try {
return painter.maxIntrinsicWidth;
} finally {
painter.dispose();
}
}
// _paragraph being null means the text needs layout because of style changes.
// Setting _paragraph to null invalidates all the layout cache.
//

View file

@ -1184,6 +1184,30 @@ void main() {
painter.dispose();
expect(painter.debugDisposed, true);
});
test('TextPainter computeWidth', () {
const InlineSpan text = TextSpan(text: 'foobar');
final TextPainter painter = TextPainter(text: text, textDirection: TextDirection.ltr);
painter.layout();
expect(painter.width, TextPainter.computeWidth(text: text, textDirection: TextDirection.ltr));
painter.layout(minWidth: 500);
expect(painter.width, TextPainter.computeWidth(text: text, textDirection: TextDirection.ltr, minWidth: 500));
painter.dispose();
});
test('TextPainter computeMaxIntrinsicWidth', () {
const InlineSpan text = TextSpan(text: 'foobar');
final TextPainter painter = TextPainter(text: text, textDirection: TextDirection.ltr);
painter.layout();
expect(painter.maxIntrinsicWidth, TextPainter.computeMaxIntrinsicWidth(text: text, textDirection: TextDirection.ltr));
painter.layout(minWidth: 500);
expect(painter.maxIntrinsicWidth, TextPainter.computeMaxIntrinsicWidth(text: text, textDirection: TextDirection.ltr, minWidth: 500));
painter.dispose();
});
}
class MockCanvas extends Fake implements Canvas {