How to disable a TextField by clicking a button - flutter

How can a button disable a TextField, so when I click the button I can't change the TextField's value?

You should change the TextField enabled property to false when the button is pressed. Here is an example:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: Center(
child: MyStatefulWidget(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
#override
_State createState() => _State();
}
class _State extends State<MyStatefulWidget> {
bool isTextFieldEnabled = true;
#override
Widget build(BuildContext context) {
return Container(
child: Column(children: [
TextField(enabled: isTextFieldEnabled,),
ElevatedButton(child: Text('Press Me To Disable TextField'),
onPressed: () {
setState(() {
isTextFieldEnabled = false;
});
},),
],)
);
}
}

you can use enabled false on text field:
TextField(
keyboardType: TextInputType.number,
enabled: false,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Current Miles',
),
),
but if you still want to handle a click on your text field you should use follow:
TextField(
readOnly: true,
enableInteractiveSelection: true,
onTap: () {
do_something(),
},
),
you need to use 'setState' on you button 'onPressed' and put any of the above needed flags in a variable and set accordingly.

Both TextField and TextFormField has a property called enabled, it's a bool, also you need to add a controller, and this can be achieved controlled by :
bool? enabled;
TextFormField(
enabled:enabled
)
//for the button
GestureDetector(onTap: () {
setState(() {
enabled = false;
});
})

Related

How to continuously get whether the TextField's text is empty in Flutter?

I have a TextField. I want its text not to be empty. (so I want to know if the text is empty)
I have tried using the following code, but it doesn't work:
controller.text.trim().isEmpty()
My code:
TextFormField(
controller: controller,
),
controller.text.trim().isEmpty()
How to continuously get whether the TextField's text is empty in Flutter? I would appreciate any help. Thank you in advance!
full example:
code:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController _controller = TextEditingController();
String _text = '';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
),
body: Container(
padding: const EdgeInsets.all(16),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(_text),
const SizedBox(height: 20),
TextField(
controller: _controller,
onChanged: (value) {
setState(() {
_text = value;
});
},
decoration: const InputDecoration(
hintText: 'Enter text',
),
),
// submit
ElevatedButton(
onPressed: _text.isEmpty
? null
: () {
setState(() {
_text = _controller.text;
});
},
child: const Text('Submit'),
),
],
),
),
),
);
}
}
It can be done without any temporary variable using ValueListenableBuilder
After some research figured out
controller.text by itself is not listenable
TextEditingController extends ValueNotifier<TextEditingValue> i.e you can use ValueListenableBuilder from material package to listen to text changes.
Code:
class _MyWidgetState extends State<MyWidget> {
late TextEditingController textEditingController;
#override
void initState() {
textEditingController = TextEditingController();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
TextField(
controller: textEditingController,
),
ValueListenableBuilder<TextEditingValue>(
valueListenable: textEditingController,
builder: (context, value, child) {
return ElevatedButton(
onPressed: value.text.isNotEmpty ? () {} : null,
child: const Text('I am disabled when text is empty'),
);
},
),
],
),
),
);
}
}
Without text:
With text:
You can add listener to your TextEditingController and call setState to update the UI.
late TextEditingController controller = TextEditingController()..addListener(() {
setState((){}); // to update the ui
});
The place you will use controller.text.trim().isEmpty() will show the updated state.
Example
class Test extends StatefulWidget {
const Test({super.key});
#override
State<Test> createState() => _TestState();
}
class _TestState extends State<Test> {
late TextEditingController controller = TextEditingController()
..addListener(() {
setState(() {}); // to update the ui
});
#override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: controller,
),
ElevatedButton(
onPressed: controller.text.trim().isEmpty ? null : () {},
child: Text("Button"))
],
);
}
}

In Flutter check a checkbox -> disabled checkbox and text field should be enabled in checkbox check

I am new to Flutter.
If I click a check box action should be performed.
Eg: Click a checkbox, enable the other checkbox and enable a text field
disable or enable widget only for button click is available.
I don't know how to do it in flutter
The idea is to use ternary operator ( ? : ) this works same as if does. Most basic explanation about code below when the checkbox is triggered checkBox1 changes and widget rebuilds with checkBox1 equals true now so instead of empty Container currently we are building new CheckBox.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool checkBox1 = false;
bool checkBox2 = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: [
CheckboxListTile(
title: Text("title text"),
value: checkBox1,
onChanged: (newValue) {
setState(() {
checkBox1 = newValue;
});
},
),
checkBox1
? CheckboxListTile(
title: Text("title text2"),
value: checkBox2,
onChanged: (newValue) {
setState(() {
checkBox2 = newValue;
});
},
)
: Container(),
],
),
);
}
}
final TextEditingController _controllerTE =
TextEditingController();
bool cbFlag = false;
TextField(
readOnly: !cbFlag,
controller: _controllerTE,
decoration: InputDecoration(
labelText: 'TE disabled till CB checked',
prefixIcon: Checkbox(
value: cbFlag,
onChanged: (bool? value) {
setState(() {
cbFlag = value!;
});
},
),
),
),

Hide keyboard upon tapping on radio button in Flutter

I am trying to find a way to dismiss the keyboard upon tapping on the radio buttons. I found some answers like this tutorial (https://flutterigniter.com/dismiss-keyboard-form-lose-focus/) but this will only hide the keyboard upon clicking outside the text field on an empty spot not tapping the radio button.
Here is a simple code if you would like to try. Any thoughts will be highly appreciated. Thanks
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: Center(
child: MyStatefulWidget(),
),
),
);
}
}
enum SingingCharacter { lafayette, jefferson }
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
SingingCharacter _character = SingingCharacter.lafayette;
Widget build(BuildContext context) {
return Column(
children: <Widget>[
TextField(
autofocus: true,
),
ListTile(
title: const Text('Lafayette'),
leading: Radio(
value: SingingCharacter.lafayette,
groupValue: _character,
onChanged: (SingingCharacter value) {
setState(() {
_character = value;
});
},
),
),
ListTile(
title: const Text('Thomas Jefferson'),
leading: Radio(
value: SingingCharacter.jefferson,
groupValue: _character,
onChanged: (SingingCharacter value) {
setState(() {
_character = value;
});
},
),
),
],
);
}
}
in onChange Function write this line of code FocusScope.of(context).unfocus();
A couple of Solutions
Using SystemChannels
import 'package:flutter/services.dart';
SystemChannels.textInput.invokeMethod('TextInput.hide');
Using FocusScope
FocusScope.of(context).unfocus();
Add this line in onChange Function
FocusScope.of(context).requestFocus(new FocusNode());

How can I enable Tab in Textfield of flutter( web version)?

I m working on a web project using Flutter web, I understand currently Flutter web is only in beta version.
Basically I m implementing a web code editor using textfield, If the user press TAB key I want to make an indent as usual. However when I press tab it either move to next element (let say I have a button below the textarea) or it do not indent at all. Anyone know how to solve this?
example code below :
Widget build(BuildContext context) {
return Container(
color: Colors.black87,
child: Padding(
padding: EdgeInsets.all(8.0),
child:TextField(
controller: controller,
onEditingComplete: (){print('editing complete');},
onTap: (){},
onChanged: (text){print(text);},
style: TextStyle(fontStyle: FontStyle.italic,color: Colors.white),
maxLines: 20,
autofocus: true,
decoration: InputDecoration.collapsed(hintText: "write code for the formation"),
),
)
);
}
}
I've accomplished adding tabs with something like this:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.dark(),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class InsertTabIntent extends Intent {
const InsertTabIntent(this.numSpaces, this.textController);
final int numSpaces;
final TextEditingController textController;
}
class InsertTabAction extends Action {
#override
Object invoke(covariant Intent intent) {
if (intent is InsertTabIntent) {
final oldValue = intent.textController.value;
final newComposing = TextRange.collapsed(oldValue.composing.start);
final newSelection = TextSelection.collapsed(
offset: oldValue.selection.start + intent.numSpaces);
final newText = StringBuffer(oldValue.selection.isValid
? oldValue.selection.textBefore(oldValue.text)
: oldValue.text);
for (var i = 0; i < intent.numSpaces; i++) {
newText.write(' ');
}
newText.write(oldValue.selection.isValid
? oldValue.selection.textAfter(oldValue.text)
: '');
intent.textController.value = intent.textController.value.copyWith(
composing: newComposing,
text: newText.toString(),
selection: newSelection,
);
}
return '';
}
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController textController;
#override
void initState() {
super.initState();
textController = TextEditingController();
}
#override
void dispose() {
textController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Actions(
actions: {InsertTabIntent: InsertTabAction()},
child: Shortcuts(
shortcuts: {
LogicalKeySet(LogicalKeyboardKey.tab):
InsertTabIntent(2, textController)
},
child: TextField(
controller: textController,
textInputAction: TextInputAction.newline,
maxLines: 30,
keyboardType: TextInputType.multiline,
),
),
),
],
),
),
);
}
}

TextFormField not focused after enabling it

I do not see a blinking cursor if I enable and focus a previous disabled TextFormField. In this example, the TextFormField is originally disabled, as indicated by the _enabled state variable, and when you click on the enable button, the field is enabled and focused but the blinking cursor is not visible. I have to click on the TextFormField in order to see the blinking cursor.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _enabled = false;
FocusNode focusNodeA = FocusNode();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test'),
),
body: TextFormField(
enabled: _enabled,
focusNode: focusNodeA,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() => _enabled = true);
FocusScope.of(context).requestFocus(focusNodeA);
},
child: Text('Enable'),
),
);
}
}
If I press 'Enable' twice, the cursor is shown.
If the TextFormField was already enabled and then focused, the blinking cursor is visible.
1- you focused after setState so it not working.
just do like below
2- you can't focus widget until disabled and when you enabling widget. when you do focusing and enabling at same time in ui tread it's try focusing before enabling because of their rendering time.if you post some delay to focusing the problem get solving.
setState(() {
Future.delayed(const Duration(milliseconds: 10), ()
{
FocusScope
.of(
context)
.requestFocus(
focusNodeA);
print(FocusScope.of(context).focusedChild.toString());
});
_enabled = true;
});
Please try
setState(() {
enableEditText = true;
Future.delayed(const Duration(milliseconds: 500), () {
tfController.selection =
TextSelection.fromPosition(TextPosition(offset: tfController.text.length));
FocusScope.of(context).requestFocus(focusNode);
});
});
TextField(
controller: tfController,
decoration: null,
textInputAction: TextInputAction.done,
enabled: enableEditText,
focusNode: focusNode,
),