How can I get the size of the Text Widget in flutter

前端 未结 5 705
不思量自难忘°
不思量自难忘° 2020-11-29 01:19

I\'ve painted a shape for the background of my content of Text.

I want the background autoscale the Text, even the softWrap being true.

相关标签:
5条回答
  • 2020-11-29 01:42

    I found another method without using the context:

    final constraints = BoxConstraints(
      maxWidth: 800.0, // maxwidth calculated
      minHeight: 0.0,
      minWidth: 0.0,
    );
    
    RenderParagraph renderParagraph = RenderParagraph(
      TextSpan(
        text: text,
        style: TextStyle(
          fontSize: fontSize,
        ),
      ),
      textDirection: ui.TextDirection.ltr,
      maxLines: 1,
    );
    renderParagraph.layout(constraints);
    double textlen = renderParagraph.getMinIntrinsicWidth(fontSize).ceilToDouble();
    
    0 讨论(0)
  • 2020-11-29 01:44

    Problem with other answers is that if you use Text widget to display your text and constraint it with measurements result without considering default font family and scale factor, then you will get wrong results because Text widget is using device's textScaleFactor by default and passing it to RichText widget inside of it. This is the correct code to measure text size:

    final Size size = (TextPainter(
            text: TextSpan(text: text, style: textStyle),
            maxLines: 1,
            textScaleFactor: MediaQuery.of(context).textScaleFactor,
            textDirection: TextDirection.ltr)
          ..layout())
        .size;
    
    0 讨论(0)
  • 2020-11-29 01:50

    A simple example:

    For how it works see inline comments.

    Inspiration from https://github.com/flutter/flutter/issues/23247

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Calc Text Size',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Calc Text Size'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      static const String loremIpsum =
          'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod '
          'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim '
          'veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea '
          'commodo consequat. Duis aute irure dolor in reprehenderit in voluptate '
          'velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint '
          'occaecat cupidatat non proident, sunt in culpa qui officia deserunt '
          'mollit anim id est laborum.';
    
      @override
      Widget build(BuildContext context) {
        final mq = MediaQuery.of(context);
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                SizedBox(
                  height: mq.size.height,
                  width: 240.0,
                  child: ListView(
                    padding: EdgeInsets.all(4.0),
                    children: <Widget>[
                      Container(
                        decoration: BoxDecoration(
                          border: Border.all(color: Colors.orange),
                        ),
                        child: Bubble(
                          text: TextSpan(
                            text: loremIpsum,
                            style: Theme.of(context).textTheme.body1,
                          ),
                        ),
                      ),
                      Container(
                        decoration: BoxDecoration(
                          border: Border.all(color: Colors.orange, width: 2.0),
                        ),
                        padding: EdgeInsets.symmetric(horizontal: 2.0),
                        child: Bubble(
                          text: TextSpan(
                            text: loremIpsum,
                            style: Theme.of(context).textTheme.body1,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class Bubble extends StatefulWidget {
      Bubble({@required this.text});
    
      final TextSpan text;
    
      @override
      _BubbleState createState() => new _BubbleState();
    }
    
    class _BubbleState extends State<Bubble> {
      @override
      Widget build(BuildContext context) {
        return LayoutBuilder(builder: (context, constraints) {
          // The text to render
          final textWidget = Text.rich(widget.text);
    
          // Calculate the left, top, bottom position of the end of the last text
          // line.
          final lastBox = _calcLastLineEnd(context, constraints);
    
          // Calculate whether the timestamp fits into the last line or if it has
          // to be positioned after the last line.
          final fitsLastLine =
              constraints.maxWidth - lastBox.right > Timestamp.size.width + 10.0;
    
          return Stack(
            children: [
              // Ensure the stack is big enough to render the text and the
              // timestamp.
              SizedBox.fromSize(
                  size: Size(
                    constraints.maxWidth,
                    (fitsLastLine ? lastBox.top : lastBox.bottom) +
                        10.0 +
                        Timestamp.size.height,
                  ),
                  child: Container()),
              // Render the text.
              textWidget,
              // Render the timestamp.
              Positioned(
                left: constraints.maxWidth - (Timestamp.size.width + 10.0),
                top: (fitsLastLine ? lastBox.top : lastBox.bottom) + 5.0,
                child: Timestamp(DateTime.now()),
              ),
            ],
          );
        });
      }
    
      // Calculate the left, top, bottom position of the end of the last text
      // line.
      TextBox _calcLastLineEnd(BuildContext context, BoxConstraints constraints) {
        final richTextWidget = Text.rich(widget.text).build(context) as RichText;
        final renderObject = richTextWidget.createRenderObject(context);
        renderObject.layout(constraints);
        final lastBox = renderObject
            .getBoxesForSelection(TextSelection(
                baseOffset: 0, extentOffset: widget.text.toPlainText().length))
            .last;
        return lastBox;
      }
    }
    
    class Timestamp extends StatelessWidget {
      Timestamp(this.timestamp);
    
      final DateTime timestamp;
    
      /// This size could be calculated similarly to the way the text size in
      /// [Bubble] is calculated instead of using magic values.
      static final Size size = Size(60.0, 25.0);
    
      @override
      Widget build(BuildContext context) => Container(
            padding: EdgeInsets.all(3.0),
            decoration: BoxDecoration(
              color: Colors.greenAccent,
              border: Border.all(color: Colors.yellow),
            ),
            child:
                Text('${timestamp.hour}:${timestamp.minute}:${timestamp.second}'),
          );
    }
    

    0 讨论(0)
  • 2020-11-29 01:50

    from inspiring of the Günter Zöchbauer

    List<bool> _calcLastLineEnd(String msg) {
      // self-defined constraint
      final constraints = BoxConstraints(
        maxWidth: 800.0, // maxwidth calculated
        minHeight: 30.0,
        minWidth: 80.0,
      );
      final richTextWidget =
          Text.rich(TextSpan(text: msg)).build(context) as RichText;
      final renderObject = richTextWidget.createRenderObject(context);
      renderObject.layout(constraints);
      final boxes = renderObject.getBoxesForSelection(TextSelection(
          baseOffset: 0, extentOffset: TextSpan(text: msg).toPlainText().length));
      bool needPadding = false, needNextline = false;
      if (boxes.length < 2 && boxes.last.right < 630) needPadding = true;
      if (boxes.length < 2 && boxes.last.right > 630) needNextline = true;
      if (boxes.length > 1 && boxes.last.right > 630) needNextline = true;
      return [needPadding, needNextline];
    }
    
    0 讨论(0)
  • 2020-11-29 01:54

    My apologies. This is not a direct answer on the topic's question! But If someone needs to get the size of a Text widget — this method can help. It helped me in creation of custom menu widget.

    class TextSized extends StatelessWidget {
      const TextSized({Key key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        final String text = "Text in one line";
        final TextStyle textStyle = TextStyle(
          fontSize: 30,
          color: Colors.white,
        );
        final Size txtSize = _textSize(text, textStyle);
    
        // This kind of use - meaningless. It's just an example.
        return Container(
          color: Colors.blueGrey,
          width: txtSize.width,
          height: txtSize.height,
          child: Text(
            text,
            style: textStyle,
            softWrap: false,
            overflow: TextOverflow.clip,
            maxLines: 1,
          ),
        );
      }
    
      // Here it is!
      Size _textSize(String text, TextStyle style) {
        final TextPainter textPainter = TextPainter(
            text: TextSpan(text: text, style: style), maxLines: 1, textDirection: TextDirection.ltr)
          ..layout(minWidth: 0, maxWidth: double.infinity);
        return textPainter.size;
      }
    }
    
    0 讨论(0)
提交回复
热议问题