281

It may sound easy but How can we do a multi-line editable textfield in flutter? TextField works only with a single line.

Edit: some precisions because seems like it's not clear. While you can set multiline to virtually wrap the text content, it's still not multiline. It's a single line displayed into multiple lines. If you want to do something like this then you can't. Because you don't have access to ENTER button. And no enter button means no multiline.

polina-c
  • 6,245
  • 5
  • 25
  • 36
Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432

16 Answers16

498

To use auto wrap, just set maxLines as null:

TextField(
  keyboardType: TextInputType.multiline,
  maxLines: null,
)

If the maxLines property is null, there is no limit to the number of lines, and the wrap is enabled.

Philippe Fanaro
  • 6,148
  • 6
  • 38
  • 76
Fellipe Sanches
  • 7,395
  • 4
  • 32
  • 33
111

If you want your TextField be adapted to the user input then do this:

TextField(
    keyboardType: TextInputType.multiline,
    minLines: 1,//Normal textInputField will be displayed
    maxLines: 5,// when user presses enter it will adapt to it
    );

here you can set the max lines to whatever you want and you are good to go. In my opinion setting the maxlines to null is not a good choice that's why we should set it to some value.

BENHISSI Youssef
  • 59
  • 2
  • 2
  • 9
taranjeet singh
  • 1,486
  • 1
  • 13
  • 11
  • 1
    I have corrected the widget name from: TextInputField, to: TextField. In flutter there is not TextInputField, just TextField or TextFormField. Unless you create one with custom name. – Cassio Seffrin Sep 01 '20 at 13:10
  • In your example, its default showing 5 lines. I want to saw 1 line only. If you want to add more data then he/she can press enter. – Pratik Butani Mar 25 '21 at 10:59
30

1. Fixed height:

enter image description here

(A) Based on lines:

TextField(
  minLines: 3, // Set this
  maxLines: 6, // and this
  keyboardType: TextInputType.multiline,
)

(B) Based on height:

SizedBox(
  height: 200, //     <-- TextField expands to this height. 
  child: TextField(
    maxLines: null, // Set this 
    expands: true, // and this
    keyboardType: TextInputType.multiline,
  ),
)

2. Flexible height:

Use a Column and wrap the TextField in Expanded:

Column(
  children: [
    Expanded(
      child: TextField(
        maxLines: null, // Set this 
        expands: true, // and this
        keyboardType: TextInputType.multiline,
      ),
    ),
  ],
)

(Optional) Set decoration:

You can se this decoration to any of the above TextField:

decoration: InputDecoration(
  hintText: 'Write a message',
  filled: true,
)
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
27

Although other people already mentioned that the keyboard type "TextInputType.multiline" can be used, I wanted to add my implementation of a TextField that automatically adapts its height when a new line is entered, as it is often desired to immitate the input behaviour of WhatsApp and similar apps.

I'm analyzing the number of '\n' chatacters in the input for this purpose each time the text is changed. This seems to be an overkill, but unfortunately I didn't find a better possibility to achieve this beahivour in Flutter so far and I didn't notice any performance problems even on older smartphones.

class _MyScreenState extends State<MyScreen> {
  double _inputHeight = 50;
  final TextEditingController _textEditingController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _textEditingController.addListener(_checkInputHeight);
  }

  @override
  void dispose() {
    _textEditingController.dispose();
    super.dispose();
  }

  void _checkInputHeight() async {
    int count = _textEditingController.text.split('\n').length;

    if (count == 0 && _inputHeight == 50.0) {
      return;
    }
    if (count <= 5) {  // use a maximum height of 6 rows 
    // height values can be adapted based on the font size
      var newHeight = count == 0 ? 50.0 : 28.0 + (count * 18.0);
      setState(() {
        _inputHeight = newHeight;
      });
    }
  }


  // ... build method here
  TextField(
    controller: _textEditingController,
    textInputAction: TextInputAction.newline,
    keyboardType: TextInputType.multiline,
    maxLines: null,
  )
Jeff S.
  • 888
  • 12
  • 17
  • 1
    Consider adding how you actually use _inputHeight to set the height of the input – Ali Nasserzadeh Jan 27 '20 at 01:54
  • 1
    As TextField can wrap the line without spliting the line with '\n' count would fail. So I'm counting text lines with this code: int count = (_textEditingController.text.length / (MediaQuery.of(context).size.width * 0.06) ).round() ; – Reginaldo Rigo Oct 02 '20 at 15:51
19

While this question is rather old, there is no extensive answer that explains how to dynamically resize the TextField with little developer effort. This is especially of major importance when the TextField is either placed in a flexbox such as ListView, SingleChildScrollView, etc. (the flexbox will not be able to determine the intrinsic size of an expandable TextField).

As suggested by many other users, build your TextField like so:

TextField(
  textInputAction: TextInputAction.newline,
  keyboardType: TextInputType.multiline,
  minLines: null,
  maxLines: null,  // If this is null, there is no limit to the number of lines, and the text container will start with enough vertical space for one line and automatically grow to accommodate additional lines as they are entered.
  expands: true,  // If set to true and wrapped in a parent widget like [Expanded] or [SizedBox], the input will expand to fill the parent.
)

How to cope with the missing intrinsic height of the TextField?

Wrap the TextField in a IntrinsicHeight class to provide the dynamically computed intrinsic height of the expandable TextField to its parent (when requested via e.g. flexbox).

tafaust
  • 1,457
  • 16
  • 32
  • 1
    textInputAction: TextInputAction.newline, - was looking for this, it makes enter input new line, thank – Jan Jun 24 '21 at 11:38
18
   TextFormField(
                  minLines: 2,
                  maxLines: 5,
                  keyboardType: TextInputType.multiline,
                  decoration: InputDecoration(
                    hintText: 'description',
                    hintStyle: TextStyle(
                      color: Colors.grey
                    ),
                    border: OutlineInputBorder(
                      borderRadius: BorderRadius.all(Radius.circular(20.0)),
                    ),
                  ),
                ),
Omar Alshyokh
  • 605
  • 5
  • 7
14

You have to use this line in the TextField widget :

maxLines: null,

if didn't work , just note that you have to delete this :

textInputAction: TextInputAction.next

it's disabling multi line property action in the keyboard ..

Amer Alzibak
  • 1,489
  • 15
  • 16
8

use this

TextFormField(
      keyboardType: TextInputType.multiline,
      maxLines: //Number_of_lines(int),)
Julian
  • 33,915
  • 22
  • 119
  • 174
8

This Code Worked for me, Also I'm able to use ENTER for web & mobile.

@override
  Widget build(BuildContext context) {
      double width = MediaQuery.of(context).size.width;
      double height = MediaQuery.of(context).size.height;
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start, 
      children: [
      Container(
        child: ConstrainedBox(
          //  fit: FlexFit.loose,
          constraints:  BoxConstraints(
            maxHeight: height,//when it reach the max it will use scroll
            maxWidth: width,
          ),
          child: const TextField(
            keyboardType: TextInputType.multiline,
            maxLines: null,
            minLines: 1,
            decoration: InputDecoration(
              fillColor: Colors.blueAccent,
              filled: true,
              hintText: "Type  ",
              border: InputBorder.none,
            ),
          ),
        ),
      )
    ]);
  }

enter image description here

UN..D
  • 543
  • 5
  • 15
6

TextField has maxLines property.

enter image description here

German Saprykin
  • 6,631
  • 2
  • 29
  • 26
  • 2
    I know that. While it wraps the content, you still can't press enter to manually create a new line. At least on android, because you don't have access to the enter button. – Rémi Rousselet Aug 28 '17 at 11:12
  • Ah, I missed that issue. I saw a similar issue dating from 2016, so I assumed it was solved. Quite sad we still can't do it. – Rémi Rousselet Aug 28 '17 at 14:12
  • 2
    It looks like this is now fixed (http://github.com/flutter/flutter/issues/8028). I tried multi-line on both iOS and Android and both can now create new lines in the text field. – Matt S. Nov 08 '17 at 03:35
  • It can actually create a new line now, but must to press the enter key twice ! – wendu Jul 19 '18 at 02:38
6

Use Expanded widget for dynamic feels

Expanded(
            child: TextField(
              keyboardType: TextInputType.multiline,
              minLines: 1,
              maxLines: 3,
            ),
          )
TuGordoBello
  • 4,350
  • 9
  • 52
  • 78
Bibin Baby
  • 163
  • 1
  • 3
4

if above once not worked for you then try add minLines also

TextField(
        keyboardType: TextInputType.multiline,
        minLines: 3,
        maxLines: null);
saigopi.me
  • 14,011
  • 2
  • 83
  • 54
3

For autowrap just use null for maxLines

TextFormField(
  keyboardType: TextInputType.multiline,
  maxLines: null,
)

or

TextField(
  keyboardType: TextInputType.multiline,
  maxLines: null,
)
Anand
  • 4,355
  • 2
  • 35
  • 45
2

Official doc states: The maxLines property can be set to null to remove the restriction on the number of lines. By default, it is one, meaning this is a single-line text field.

NOTE: maxLines must not be zero.

Jitesh Prajapati
  • 2,533
  • 4
  • 29
  • 51
mickyliu
  • 21
  • 1
2

Specify TextInputAction.newline to make a TextField respond to the enter key and accept multi-line input:

textInputAction: TextInputAction.newline,
AWhitford
  • 3,708
  • 3
  • 28
  • 38
2

use this

 Expanded(
        child: TextField(
          controller: textMessageController,
          keyboardType: TextInputType.multiline,
          textCapitalization: TextCapitalization.sentences,
          minLines: 1,
          maxLines: 3,
          onChanged: ((value) {
            setState(() {
              _messageEntrer = value;
            });
          }),
          decoration: InputDecoration(
            hintText: "Type your message here",
            hintMaxLines: 1,
            contentPadding:
                const EdgeInsets.symmetric(horizontal: 8.0, vertical: 10),
            hintStyle: TextStyle(
              fontSize: 16,
            ),
            fillColor: Colors.white,
            filled: true,
            enabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(30.0),
              borderSide: const BorderSide(
                color: Colors.white,
                width: 0.2,
              ),
            ),
            focusedBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(30.0),
              borderSide: const BorderSide(
                color: Colors.black26,
                width: 0.2,
              ),
            ),
          ),
        ),
      ),
teddy 225
  • 81
  • 1