Rémi Rousselet
Rémi Rousselet

Reputation: 277567

Multi-line TextField in Flutter

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.

Upvotes: 319

Views: 289881

Answers (19)

Muhammed Faseen C M
Muhammed Faseen C M

Reputation: 9

To create a multi-line editable text field in Flutter, you can use the TextField widget along with the maxLines parameter set to null or a value greater than 1. This allows the text field to accept multiple lines of input. Additionally, you can set the KeyboardType parameter to TextInputType.multiline to allow users to multiline text

TextField(
          controller: _controller,
          keyboardType: TextInputType.multiline,
          maxLines: null, // Allows for unlimited lines
          decoration: InputDecoration(
            hintText: 'Enter your text here',
            border: OutlineInputBorder(),
          ),
        ),

Upvotes: -1

rockstarr-programmerr
rockstarr-programmerr

Reputation: 506

I don't see how to address the vertical alignment of the label in any answer. When you follow any of the accepted approaches (using minLines or SizedBox), you'll see that the label is vertically aligned to the center of the input, when you type some text into the input, those text will also be vertically aligned to the center. This is not necessarily what most people expected. Here is how to align both of them to the top.

The 2 important attributes are alignLabelWithHint: true and textAlignVertical: const TextAlignVertical(y: -1)

TextFormField(
  decoration: const InputDecoration(
    labelText: 'My input',
    alignLabelWithHint: true,  // This align the label to the top
  ),
  keyboardType: TextInputType.multiline,
  maxLines: null,
  minLines: 4,
  textAlignVertical: const TextAlignVertical(y: -1),  // This align the input text to the top
)

Upvotes: 0

Michael Sacks
Michael Sacks

Reputation: 917

'\n' and "\n" behave differently. It's important to note the difference between " and '

Upvotes: 0

Amer Al zibak
Amer Al zibak

Reputation: 1961

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 ..

Upvotes: 18

CopsOnRoad
CopsOnRoad

Reputation: 268314

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,
)

Upvotes: 46

teddy 225
teddy 225

Reputation: 111

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,
              ),
            ),
          ),
        ),
      ),

Upvotes: 3

Bibin Baby
Bibin Baby

Reputation: 188

Use Expanded widget for dynamic feels

Expanded(
            child: TextField(
              keyboardType: TextInputType.multiline,
              minLines: 1,
              maxLines: 3,
            ),
          )

Upvotes: 6

Anandh Krishnan
Anandh Krishnan

Reputation: 6022

For autowrap just use null for maxLines

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

or

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

Upvotes: 3

taranjeet singh
taranjeet singh

Reputation: 1646

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.

Upvotes: 125

UN..D
UN..D

Reputation: 603

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

Upvotes: 8

tafaust
tafaust

Reputation: 1518

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).

Upvotes: 23

Omar Alshyokh
Omar Alshyokh

Reputation: 665

   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)),
                    ),
                  ),
                ),

Upvotes: 18

AWhitford
AWhitford

Reputation: 4008

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

textInputAction: TextInputAction.newline,

Upvotes: 3

Jeff S.
Jeff S.

Reputation: 1006

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,
  )

Upvotes: 27

Fellipe Sanches
Fellipe Sanches

Reputation: 8155

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.

Upvotes: 553

saigopi.me
saigopi.me

Reputation: 14938

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

TextField(
        keyboardType: TextInputType.multiline,
        minLines: 3,
        maxLines: null);

Upvotes: 4

mickyliu
mickyliu

Reputation: 21

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.

Upvotes: 2

Muhannad Mahamooad
Muhannad Mahamooad

Reputation: 169

use this

TextFormField(
      keyboardType: TextInputType.multiline,
      maxLines: //Number_of_lines(int),)

Upvotes: 8

German Saprykin
German Saprykin

Reputation: 6961

TextField has maxLines property.

enter image description here

Upvotes: 6

Related Questions