Disable a text edit field in flutter
Asked Answered
R

19

135

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?

Rhonarhonchus answered 12/6, 2017 at 2:30 Comment(3)
Filed github.com/flutter/flutter/issues/10645Arcade
For people from google, you can now add a flag on the widget, see my answer.Reneerenegade
@Rhonarhonchus can you change the accepted answer to one of the more recent ones because the framework now supports thisPember
P
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',
              ),
            ),
          ),
        ),
      ),
    );
  }
}
Pressey answered 12/6, 2017 at 3:14 Comment(1)
no need to add this? FocusScopeNode(canRequestFocus: _enabled, child: .....Hegemony
S
194
TextFormField(
readOnly: true,
)
Sinh answered 24/7, 2019 at 17:54 Comment(4)
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.Eyepiece
It's what I looking for, enabled: false makes the suffix iconbutton disabled (I use content_copy icon to copy). But this one worksEmbryology
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.Esdraelon
I do not like using readOnly: true since, when focusing on the readOnly field, its size is reduced.Schilit
C
183

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.

Cush answered 12/2, 2018 at 8:5 Comment(6)
Yes, you can have a TextFormatter that ignore any input (through paste), but return the source to avoid this behaviour :)Cush
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 ;)Surinam
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...Babin
@Babin why not use my first solution, AlwaysDisabledFocusNode?Cush
@HemanthRaj I tried it too. I don't remember the problem now, but it also prevented some desired behavior.Babin
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.Langevin
U
89

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.

Ulster answered 29/5, 2018 at 8:0 Comment(7)
This is the actual answer.Thiele
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.Closefisted
This is the actual answer!Edlyn
the problem with enabled=false that it prevents error message appearanceValency
enabled=false does not do anythingEchopraxia
This is the answer I wanted. Simple and solidTibbetts
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.Hollis
M
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.

Monosome answered 20/3, 2019 at 4:18 Comment(1)
This is exactly what I need form my calendar input. Thanks!Dasher
P
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',
              ),
            ),
          ),
        ),
      ),
    );
  }
}
Pressey answered 12/6, 2017 at 3:14 Comment(1)
no need to add this? FocusScopeNode(canRequestFocus: _enabled, child: .....Hegemony
A
24

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

Allergic answered 17/1, 2019 at 19:46 Comment(3)
This is exactly what I was looking for. ThanksShout
It's not needed. There's readOnly propertyTouchmenot
@Touchmenot readOnly still makes it able to focus thus the blue line and label going upIntaglio
M
21

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.

Midwinter answered 30/7, 2020 at 7:55 Comment(2)
This is the best answer! Thanks a lot!Deferral
in onTap function try to use FocusScope.of(context).unfocus(); it will disabled the writting modeMaryettamaryjane
S
21

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.

Sensate answered 26/11, 2020 at 7:54 Comment(0)
T
13

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
);
Thaddeus answered 4/9, 2019 at 16:40 Comment(1)
This works for me. The absorbing param will default to true so u omitArchimedes
H
13

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]

Heracles answered 10/2, 2022 at 17:9 Comment(0)
R
12

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

TextField(enabled: false)
Reneerenegade answered 12/3, 2019 at 13:12 Comment(1)
probably best answer, I wonder why it's not up votedParonomasia
V
10
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,
      ),
    );
Videogenic answered 18/5, 2022 at 15:36 Comment(0)
E
9

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

TextFormField(
    enabled: false,
)
Elaterid answered 1/6, 2021 at 7:18 Comment(0)
I
2
                    readOnly: true,
                    enableInteractiveSelection: false,
                    onTap: () {
                      FocusScope.of(context).requestFocus(FocusNode());
                    },
Inge answered 13/7, 2023 at 14:1 Comment(0)
N
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)),
  ),
Necessarily answered 28/7, 2020 at 9:4 Comment(0)
H
0

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

FocusScope.of(context).requestFocus(titleFocusNode);
titleFocusNode.consumeKeyboardToken();
Howund answered 6/12, 2021 at 11:31 Comment(0)
J
0

It's working for me

TextField(
          readOnly: true,
         onChanged: (value) { },
        )
Juliennejuliet answered 1/1, 2022 at 13:59 Comment(0)
I
0

You can use enable to false disable the form field

TextFormField(         
    enabled: false,
)

Or you can use readOnly to false to make the form field read-only

TextFormField(         
        readOnly: false,
    )
Ivett answered 4/4 at 10:46 Comment(0)
K
-1

For that... TextField:

TextField(
          readOnly: true,
          enableInteractiveSelection: false,
          enabled: false,
        )
Kroon answered 18/9, 2023 at 14:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.