在颤动中禁用文本编辑字段

我需要偶尔禁用 TextFormField。我无法在小部件中找到一个标志,也无法在控制器中简单地将其设置为只读或禁用。 最好的方法是什么?

160930 次浏览

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',
),
),
),
),
),
);
}
}

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.

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.

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

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

TextField(enabled: false)

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.

TextFormField(
readOnly: true,
)

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

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

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.

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.

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

TextFormField(
enabled: false,
)

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

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

It's working for me

TextField(
readOnly: true,
onChanged: (value) { },
)

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]

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