What is the meaning Flutter's width metrics for the Paragraph class?
Asked Answered
S

1

6

The documentation for Paragraph has four different ways to get a width distance:

width → double
The amount of horizontal space this paragraph occupies.

longestLine → double
The distance from the left edge of the leftmost glyph to the right edge of the rightmost glyph in the paragraph.

maxIntrinsicWidth → double
Returns the smallest width beyond which increasing the width never decreases the height.

minIntrinsicWidth → double
The minimum width that this paragraph could be without failing to paint its contents within itself.

Note that tightWidth no longer appears in the Flutter 1.7 stable version.

I still don't understand clearly how these are different, though. Does width include some extra padding?

Schoenfeld answered 17/7, 2019 at 20:26 Comment(0)
S
19

In the following examples, the following text is used:

Hello, world.
Another line of text.
A line of text that wraps around.

The red rectangles are meant to illustrate the width metrics. The height can be ignored.

width

This is the width of the paragraph as defined by the ParagraphConstraints width argument when the paragraph is laid out. It does not depend of the content of the paragraph text.

enter image description here

longestLine

This is the length of the longest line of text with the soft wrapping taken into account. It will be less than or equal to the paragraph width.

enter image description here

maxIntrinsicWidth

This is how wide the paragraph would like to be if it had its choice. It's the width of the longest line when there is no soft line wrapping. That is, it is the width of what "A line of text that wraps around." would be if it hadn't been forced onto a new line.

enter image description here

minIntrinsicWidth

This is the narrowest the paragraph could be without causing some word to be broken unnaturally. You can see in the example below that the minIntrinsicWidth is the width of the word "Another".

enter image description here

Supplemental code

You can create a new Flutter project and replace main.dart with the following code if you would like to play around with it yourself.

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:ui' as ui;

void main() {
  debugPaintSizeEnabled = false;
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.white,
        body: HomeWidget(),
      ),
    );
  }
}

class HomeWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: CustomPaint(
        size: Size(300, 200),
        painter: MyPainter(),
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {

    final text = 'Hello, world.\nAnother line of text.\nA line of text that wraps around.';

    // draw the text
    final textStyle = ui.TextStyle(
      color: Colors.black,
      fontSize: 30,
    );
    final paragraphStyle = ui.ParagraphStyle(
      textDirection: TextDirection.ltr,
    );
    final paragraphBuilder = ui.ParagraphBuilder(paragraphStyle)
      ..pushStyle(textStyle)
      ..addText(text);
    final constraints = ui.ParagraphConstraints(width: 300);
    final paragraph = paragraphBuilder.build();
    paragraph.layout(constraints);
    final offset = Offset(0, 0);
    canvas.drawParagraph(paragraph, offset);

    // draw a rectangle around the text
    final left = 0.0;
    final top = 0.0;
    //final right = paragraph.width;
    //final right = paragraph.longestLine;
    //final right = paragraph.maxIntrinsicWidth;
    final right = paragraph.minIntrinsicWidth;
    final bottom = paragraph.height;
    final rect = Rect.fromLTRB(left, top, right, bottom);
    final paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1;
    canvas.drawRect(rect, paint);
  }

  @override
  bool shouldRepaint(CustomPainter old) {
    return false;
  }
}

See also

Schoenfeld answered 17/7, 2019 at 20:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.