Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

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

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.

So, I need to get the width and height of my Text Widget before Widget build(BuildContext context).

Actually, I am simulating the chat bubble effect like iOS message using flutter. Here is the iOS version tutorial. Creating a Chat Bubble .

The core code below:

let label =  UILabel()
label.numberOfLines = 0
label.font = UIFont.systemFont(ofSize: 18)
label.textColor = .white
label.text = text

let constraintRect = CGSize(width: 0.66 * view.frame.width,
                            height: .greatestFiniteMagnitude)
let boundingBox = text.boundingRect(with: constraintRect,
                                    options: .usesLineFragmentOrigin,
                                    attributes: [.font: label.font],
                                    context: nil)
label.frame.size = CGSize(width: ceil(boundingBox.width),
                          height: ceil(boundingBox.height))

let bubbleSize = CGSize(width: label.frame.width + 28,
                             height: label.frame.height + 20)

let width = bubbleSize.width
let height = bubbleSize.height

=========================================
SOLUTION
Here is my solution.

bubble.dart:

// Define a CustomPainter to paint the bubble background.
class BubblePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()
      ..color = Color(0xff188aff)
      ..style = PaintingStyle.fill;
    final Path bubble = Path()
      ..moveTo(size.width - 22.0, size.height)
      ..lineTo(17.0, size.height)
      ..cubicTo(
          7.61, size.height, 0.0, size.height - 7.61, 0.0, size.height - 17.0)
      ..lineTo(0.0, 17.0)
      ..cubicTo(0.0, 7.61, 7.61, 0.0, 17.0, 0.0)
      ..lineTo(size.width - 21, 0.0)
      ..cubicTo(size.width - 11.61, 0.0, size.width - 4.0, 7.61,
          size.width - 4.0, 17.0)
      ..lineTo(size.width - 4.0, size.height - 11.0)
      ..cubicTo(size.width - 4.0, size.height - 1.0, size.width, size.height,
          size.width, size.height)
      ..lineTo(size.width + 0.05, size.height - 0.01)
      ..cubicTo(size.width - 4.07, size.height + 0.43, size.width - 8.16,
          size.height - 1.06, size.width - 11.04, size.height - 4.04)
      ..cubicTo(size.width - 16.0, size.height, size.width - 19.0, size.height,
          size.width - 22.0, size.height)
      ..close();
    canvas.drawPath(bubble, paint);
  }

  @override
  bool shouldRepaint(BubblePainter oldPainter) => true;
}

// This is my custom RenderObject.
class BubbleMessage extends SingleChildRenderObjectWidget {
  BubbleMessage({
    Key key,
    this.painter,
    Widget child,
  }) : super(key: key, child: child);

  final CustomPainter painter;

  @override
  RenderCustomPaint createRenderObject(BuildContext context) {
    return RenderCustomPaint(
      painter: painter,
    );
  }

  @override
  void updateRenderObject(
      BuildContext context, RenderCustomPaint renderObject) {
    renderObject..painter = painter;
  }
}

Use the BubbleMessage Widget like this:

import 'bubble.dart' 

...code ... 

BubbleMessage(
  painter: BubblePainter(),
  child: Container(
    constraints: BoxConstraints(
      maxWidth: 250.0,
      minWidth: 50.0,
    ),
    padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 6.0),
    child: Text(
      'your text variable',
      softWrap: true,
      style: TextStyle(
        fontSize: 16.0,
      ),
    ),
  ),
),

...code ...

The bubble effect:

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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;
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...