122

I need to disable TextFormField occasionally. I couldn't find a flag in the widget, or the controller to simply make it read-only or disable. What is the best way to do it?

Arash
  • 11,697
  • 14
  • 54
  • 81

17 Answers17

179

There is another way this can be achieved which also does not cause this issue. Hope this might help someone.

Create AlwaysDisabledFocusNode and pass it to the focusNode property of a TextField.

class AlwaysDisabledFocusNode extends FocusNode {
  @override
  bool get hasFocus => false;
}

then

new TextField(
    enableInteractiveSelection: false, // will disable paste operation
    focusNode: new AlwaysDisabledFocusNode(),
    ...
    ...
)

Update: TextField now has enabled property. Where you can just disable the TextField like

new TextField(
    enabled: false, 
    ...
    ...
)

Note: This will also disable icon associated with text input.

Hemanth Raj
  • 32,555
  • 10
  • 92
  • 82
  • Yes, you can have a TextFormatter that ignore any input (through paste), but return the source to avoid this behaviour :) – Hemanth Raj Jan 24 '19 at 08:48
  • 1
    I found a simpler one, in my case I used your solution and just ignored the popup to prompt the paste using `enableInteractiveSelection: false` for the `TextField` ;) – MoGa Jan 24 '19 at 18:23
  • 1
    enable=false; doesn't dispatch onTap() event. I want it disabled and not focusable but I don't want it dead. I want to have control over it. It should still fire onTap() if set. Not even if wrapping it in a GestureDetector. Man this flutter can be disappointing some times... – Dpedrinha Nov 21 '19 at 04:27
  • 1
    @Dpedrinha why not use my first solution, `AlwaysDisabledFocusNode`? – Hemanth Raj Nov 21 '19 at 16:43
  • @HemanthRaj I tried it too. I don't remember the problem now, but it also prevented some desired behavior. – Dpedrinha Nov 22 '19 at 04:49
  • `enabled=false` also disables scroll, `onTap` and more. `AlwaysDisabledFocusNode` hides text selection (the semi-transparent box you get when long tap to copy the text). I wish a proper readonly option was there. – quartzsaber Feb 22 '23 at 16:23
172
TextFormField(
readOnly: true,
)
Peter Adepojú
  • 1,779
  • 1
  • 9
  • 2
  • 1
    In order to create a more robust answer, you should add some context of what your code is doing. For more help, see [how to answer](https://stackoverflow.com/help/how-to-answer). – technogeek1995 Jul 24 '19 at 18:12
  • 2
    It's what I looking for, enabled: false makes the suffix iconbutton disabled (I use content_copy icon to copy). But this one works – mirkancal Aug 16 '19 at 13:58
  • 2
    There's a problem with readOnly:true - When user selects this control - the blue borders come up - which is basically saying that it's allowing focus to the control. – abhijat_saxena Sep 07 '20 at 11:17
  • I do not like using readOnly: true since, when focusing on the readOnly field, its size is reduced. – Jean-Pierre Schnyder May 13 '22 at 07:03
86

TextField and TextFormField both have an argument called enabled. You can control it using a boolean variable. enabled=true means it will act as an editing text field whereas enabled=false will disable the TextField.

vipin agrahari
  • 2,691
  • 3
  • 21
  • 31
Vikas
  • 1,093
  • 11
  • 13
  • 8
    This is the actual answer. – Hahnemann Jul 25 '18 at 03:41
  • 1
    It depends on your needs. Both solve the issue but Hemanth Raj solution does not disable the icon associated with the text input(put some grey color over your accentColor theme) which might tell the user he has nothing to complete (maybe you want the user to click on a modal and complete that field with default values). For just disabling an input Vikas Pandey answer should be the accepted one. – Matias Jul 26 '18 at 17:50
  • 1
    This is the actual answer! – Aryeetey Solomon Aryeetey Jan 24 '19 at 13:54
  • 2
    the problem with `enabled=false` that it prevents error message appearance – Mohamed Ali Mar 22 '19 at 12:08
  • enabled=false does not do anything – Nijat Mursali Apr 24 '21 at 12:48
  • This is the answer I wanted. Simple and solid – Geono May 09 '21 at 17:11
  • Best answer: `enabled=false` is more suitable then `readOnly=true`, since the latter doesn't block any interaction whereas `enabled=false` really disables the `TextField` or `TextFormField`. – jonashackt Jan 21 '23 at 10:14
32

Similar to readonly like in html

TextField(
    enableInteractiveSelection: false,
    focusNode: FocusNode(),
)

This can response to onTap.


Similar to disabled like in html

TextField(
    enable: false
)

This can not response to onTap.

JChen___
  • 3,593
  • 2
  • 20
  • 12
27

This isn't a feature that is currently provided by the framework, but you can use a FocusScope to prevent a TextFormField from requesting focus.

Here's what it looks like when it's disabled.

(with hint text) empty and readonly

(with a readonly value) readonly

Here's what it looks like when it's enabled.

(with focus) focused

(without focus) editable

Code for this is below:

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
    home: new HomePage(),
  ));
}

class HomePage extends StatefulWidget {
  HomePageState createState() => new HomePageState();
}

class HomePageState extends State<HomePage> {

  TextEditingController _controller = new TextEditingController();
  bool _enabled = false;

  @override
  Widget build(BuildContext context) {
    ThemeData theme = Theme.of(context);
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Disabled Text'),
      ),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.free_breakfast),
        onPressed: () {
          setState(() {
            _enabled = !_enabled;
          });
        }
      ),
      body: new Center(
        child: new Container(
          margin: const EdgeInsets.all(10.0),
          child: _enabled ?
          new TextFormField(controller: _controller) :
          new FocusScope(
            node: new FocusScopeNode(),
            child: new TextFormField(
              controller: _controller,
              style: theme.textTheme.subhead.copyWith(
                color: theme.disabledColor,
              ),
              decoration: new InputDecoration(
                hintText: _enabled ? 'Type something' : 'You cannot focus me',
              ),
            ),
          ),
        ),
      ),
    );
  }
}
Collin Jackson
  • 110,240
  • 31
  • 221
  • 152
  • 1
    no need to add this? `FocusScopeNode(canRequestFocus: _enabled, child: .....` – MBK Jun 23 '21 at 11:43
22

This is another way of somehow disabling a TextField but keeping it's functionality. I mean for onTap usage

TextField(
    enableInteractiveSelection: false,
    onTap: () { FocusScope.of(context).requestFocus(new FocusNode()); },
)
  • enableInteractiveSelection

    will disable content selection of TextField

  • FocusScope.of(context).requestFocus(new FocusNode());

    change the focus to an unused focus node

Using this way, you can still touch TextField but can't type in it or select it's content. Believe me it's going to be useful sometimes ( datepicker, timepicker, ... ) :)

Community
  • 1
  • 1
Pars
  • 4,932
  • 10
  • 50
  • 88
20

I have used a combination of readOnly and enableInteractiveSelection properties to achieve the desired behavior on TextField.

TextField(
  readOnly: true,
  enableInteractiveSelection: true,
  onTap: () {
    do_something(),
  },
)

With enableInteractiveSelection set to true, it will allow onTap() to function as normal.

1DD
  • 285
  • 4
  • 8
20

Use readOnly:true is correct. But if you still want focus to this text field you can follow below code:

TextFormField(
  showCursor: true,//add this line
  readOnly: true
)

And if you want hide text pointer (cursor), you need set enableInteractiveSelection to false.

Doan Bui
  • 3,572
  • 25
  • 36
12

There is now a way to disable TextField and TextFormField. See github here. Use it like this:

TextField(enabled: false)
Benten
  • 1,014
  • 12
  • 17
12

I tried using FocuseNode(), enabled = false yet not working, Instead of that I use a widget called AbsorbPointer. It's use for preventing a widget from touch or tap, I wrap my TextFormField or other widget inside AbsordPointer Widgets and give a parameter to disable from touch

Example

AbsorbPointer(
      absorbing: true,  //To disable from touch use false while **true** for otherwise
      child: Your WidgetsName
);
SilenceCodder
  • 2,874
  • 24
  • 28
11

For that... TextField has two properties:

TextField(
          readOnly: true,
          enabled: false,
        )

1- If you desire to disable the TextField typing and taping set [enabled: false]

2- If you desire to disable only TextField typing set [readOnly: true]

Andrew Amin
  • 491
  • 4
  • 6
9

It has enabled key, this is doing fine for me.

TextFormField(
    enabled: false,
)
Manoj Perumarath
  • 9,337
  • 8
  • 56
  • 77
5
TextField
(
   enable: false
)

Or

TextFormField(
    enable: false
)

if you use InputDecoration don't forget to set disabledBorder like this

TextFormField(
      enabled: false,
      decoration: InputDecoration(
        enabledBorder: OutlineInputBorder(
          borderRadius: BorderRadius.circular(10.0),
          borderSide: BorderSide(color: Colors.blue),
        ),
        disabledBorder:  OutlineInputBorder(
          borderRadius: BorderRadius.circular(10.0),
          borderSide: BorderSide(color: Colors.gray),
        ),
        filled: true,
      ),
    );
Mini Titan
  • 311
  • 4
  • 7
1

Use readOnly: true

TextField(
  readOnly: true,
  controller: controller,
  obscureText: obscureText,
  onChanged: (value) {
    onValueChange();
  },
  style: TextStyle(
    color: ColorResource.COLOR_292828,
    fontFamily: Font.AvenirLTProMedium.value,
    fontSize: ScreenUtil().setHeight(Size.FOURTEEN)),
    decoration: InputDecoration(
    border: InputBorder.none,
    hintText: hint,
    hintStyle: TextStyle(
      fontSize: ScreenUtil().setHeight(Size.FOURTEEN),
      color: ColorResource.COLOR_HINT,
      fontFamily: Font.AvenirLTProBook.value)),
  ),
mechnicov
  • 12,025
  • 4
  • 33
  • 56
gowthaman C
  • 472
  • 6
  • 16
0

Remove native keyboard then focus TextField programmaticaly (for example, after click emoji button):

FocusScope.of(context).requestFocus(titleFocusNode);
titleFocusNode.consumeKeyboardToken();
0

It's working for me

TextField(
          readOnly: true,
         onChanged: (value) { },
        )
0
                    readOnly: true,
                    enableInteractiveSelection: false,
                    onTap: () {
                      FocusScope.of(context).requestFocus(FocusNode());
                    },
FAIZAN KHAN
  • 11
  • 1
  • 4