2

I have a TextField (not a Text) widget that must remain on one line. I want to reduce it's font size if the text entered is too large for the TextField box, ie shrink it if it overflows. How can I do this?

I have written some code like this in a stateful component

if (textLength < 32) { newAutoTextVM.fontSize = 35.0; } else if (textLength < 42) { newAutoTextVM.fontSize = 25.0; 

In the view

fontSize: 25.0, 

but it isn't very intelligent, it doesn't cope with resizing, also, because the font size isn't monospaced (courier etc), different characters take up different amounts of space.

2 Answers 2

5

Use a TextPainter to calculate the width of your text. Use a GlobalKey to get the size of your widget (A LayoutBuilder might be better to handle screen rotation).

import 'package:flutter/material.dart'; main() => runApp(MaterialApp(home: Home())); class Home extends StatefulWidget { @override _HomeState createState() => _HomeState(); } const textFieldPadding = EdgeInsets.all(8.0); const textFieldTextStyle = TextStyle(fontSize: 30.0); class _HomeState extends State<Home> { final TextEditingController _controller = TextEditingController(); final GlobalKey _textFieldKey = GlobalKey(); double _textWidth = 0.0; double _fontSize = textFieldTextStyle.fontSize; @override void initState() { super.initState(); _controller.addListener(_onTextChanged); } void _onTextChanged() { // substract text field padding to get available space final inputWidth = _textFieldKey.currentContext.size.width - textFieldPadding.horizontal; // calculate width of text using text painter final textPainter = TextPainter( textDirection: TextDirection.ltr, text: TextSpan( text: _controller.text, style: textFieldTextStyle, ), ); textPainter.layout(); var textWidth = textPainter.width; var fontSize = textFieldTextStyle.fontSize; // not really efficient and doesn't find the perfect size, but you got all you need! while (textWidth > inputWidth && fontSize > 1.0) { fontSize -= 0.5; textPainter.text = TextSpan( text: _controller.text, style: textFieldTextStyle.copyWith(fontSize: fontSize), ); textPainter.layout(); textWidth = textPainter.width; } setState(() { _textWidth = textPainter.width; _fontSize = fontSize; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Autosize TextField'), ), body: Padding( padding: EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ TextField( key: _textFieldKey, controller: _controller, decoration: InputDecoration( border: InputBorder.none, fillColor: Colors.orange, filled: true, contentPadding: textFieldPadding, ), style: textFieldTextStyle.copyWith(fontSize: _fontSize), ), Text('Text width:'), Container( padding: textFieldPadding, color: Colors.orange, child: Row( children: <Widget>[ Container(width: _textWidth, height: 20.0, color: Colors.blue), ], ), ) ], ), ), ); } } 
Sign up to request clarification or add additional context in comments.

2 Comments

That's great, I was just experimenting with TextPainter but you beat me to it :-)
I'm not sure if my code handles screen rotation or other width changes correctly. You probably want to use a LayoutBuilder to get the width of the TextField
-1

I have searched through the docs and found a couple of solutions that could come at your help:

  • L̶o̶o̶k̶ ̶a̶t̶ ̶t̶h̶e̶ ̶o̶f̶f̶i̶c̶i̶a̶l̶ ̶d̶o̶c̶s̶[̶1̶]̶,̶ ̶i̶n̶ ̶p̶a̶r̶t̶i̶c̶u̶l̶a̶r̶e̶ ̶a̶t̶ ̶t̶h̶e̶s̶e̶ ̶p̶r̶o̶p̶e̶r̶t̶i̶e̶s̶:̶ ̶ ̶m̶a̶x̶L̶i̶n̶e̶s̶,̶ ̶o̶v̶e̶r̶f̶l̶o̶w̶ ̶a̶n̶d̶ ̶s̶o̶f̶t̶W̶r̶a̶p̶ (These are TextBox properties, not TextFields)
  • Have a look at this thread where they suggest to wrap the TextBox/TextFeld with a Flexible Widget

Depending on the rest of your code one of these solutions could be better, try tweaking around.
Hope it helps.

2 Comments

thank you but TextField doesn't have those properties (these all apply to Text)
You're right, I misread the type of Text you were referring too. But the Flexible solution should still apply: stackoverflow.com/questions/44579918/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.