I am creating an weather app in which I am providing a location string to a TextField and fetch the text inside in it. I know I can do it if I use TextField widget every time, but I want to use code reusability and that's why I have created a different Widget called TextFieldWidget in which I am providing a hint variable, which returns the Text inside it. I don't know how to do return the text. This is my code.
import 'package:flutter/material.dart';
class TextFieldWidget extends StatefulWidget {
final String _hint;
TextFieldWidget(this._hint);
#override
_TextFieldWidgetState createState() => _TextFieldWidgetState();
}
class _TextFieldWidgetState extends State<TextFieldWidget> {
TextEditingController _textEditingController;
InputDecoration _inputdecoration;
#override
void initState() {
super.initState();
_textEditingController = TextEditingController();
_inputdecoration = InputDecoration(hintText: widget._hint,floatingLabelBehavior: FloatingLabelBehavior.always);
}
#override
Widget build(BuildContext context) {
return TextField(
autocorrect: true,
controller: _textEditingController,
keyboardType: TextInputType.text,
enableSuggestions: true,
decoration: _inputdecoration,
onSubmitted: (value){
// somehow return data
// I want to access this part..
},
);
}
}
1. You have to create one method inside calling class
void _setTextValue(String value) {
// Submitted text should appear here from value
}
TextFieldWidget(_setTextValue)
2. Use this inside TextFormField then
final Function _setValue;
TextFieldWidget(this._setValue);
3. Inside onSubmitted Call
widget._setValue(value);
Finally, you will get value inside calling class
Edited:
We can add callbacks in calling widgets itself with named parameters which is correct way of doing this
Example:
class _TextFieldWidgetState extends State<TextFieldWidget> {
TextEditingController _textEditingController;
InputDecoration _inputdecoration;
#override
void initState() {
super.initState();
_textEditingController = TextEditingController();
_inputdecoration = InputDecoration(hintText: 'UserName',floatingLabelBehavior: FloatingLabelBehavior.always);
}
#override
Widget build(BuildContext context) {
return TextField(
autocorrect: true,
controller: _textEditingController,
keyboardType: TextInputType.text,
enableSuggestions: true,
decoration: _inputdecoration,
onSubmitted: (value){
widget.getUserName(value);
// somehow return data
// I want to access this part..
},
);
}
}
Call above code like
TextFieldWidget(getUserName: (value) {
// Get the username here
print(value);
}),
Note: We can add as many as named parameter like this
Related
I created a widget for a textfield that accepts password and I made use of stateful widget. Now I want to get the value of what is written in the text field in two different files but I can't make the texteditingcontroller requiredenter image description here
Login Page should be something like this:
declare the controller in the login page then you can pass the controller to other Widget including Passwordfield, the Login page now is the owner of the controller it initialize it and dispose it.
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
late TextEditingController _passwordController;
#override
void initState() {
_passwordController = TextEditingController();
}
#override
void dispose() {
_passwordController.dispose();
}
Widget build(BuildContext context) {
return Column(
children: <Widget>[
// Emailfield(),
Passwordfield(
controller: _passwordController,
),
],
);
}
}
in the Passwordfield edit the constructor to use the controller in this Widget:
class Passwordfield extends StatefulWidget {
final TextEditingController controller;
Passwordfield({Key? key, required this.controller,}) : super(key: key);
#override
_PasswordfieldState createState() => _PasswordfieldState();
}
class _PasswordfieldState extends State<Passwordfield> {
ValueChanged<String> onChanged = (value) {};
String hintText = "password";
bool hidepassword = true;
Widget build(BuildContext context) {
return TextField(
controller: widget.controller,
onChanged: onChanged,
obscureText: hidepassword,
// ...
);
}
}
You can make it like this:
First you have to create controller :
var _controller = TextEditingController();
Second add this controller to your textfield
TextField(
autofocus: true,
controller: _controller, // add controller here
decoration: InputDecoration(
hintText: 'Test',
focusColor: Colors.white,
),
),
and finally in your button check if controller is empty or not
CustomButton(
onTap: () async {
if (_controller.text.trim().isEmpty) {
showCustomSnackBar(
'Password field is empty',
context);
}
}
)
just it
I have a reusable TextFormField Widget for decimal number inputs. If the user input a decimal number with a comma instead of a dot I want to replace it. So for that I created a reusable TextFormField Widget where I want to replace the comma with a dot before the onChanged method. But how can I call the function replaceCommaWithDot() before onChanged gets called?
This is the reusable Widget:
class DecimalTextFormField extends StatelessWidget {
const DecimalTextFormField({Key? key, this.onChanged})
: super(key: key);
final ValueChanged? onChanged;
#override
Widget build(BuildContext context) {
replaceCommaWithDot(String inputNumber) {
if (inputNumber.contains(',')) {
String newText = inputNumber.replaceAll(',', '.');
return newText;
}
return inputNumber;
}
return TextFormField(
keyboardType: const TextInputType.numberWithOptions(decimal: true),
// how to use replaceCommaWithDot method when onChanged gets called?
onChanged: onChanged,
);
}
}
Your snippet will work fine if you just want result(without ui update).
onChanged: (value) {
final v = replaceCommaWithDot(value);
if (onChanged != null) onChanged!(v);
},
If you also wish to update the UI, you can use inputFormatters
class CustomFormater extends TextInputFormatter {
replaceCommaWithDot(String inputNumber) {
if (inputNumber.contains(',')) {
String newText = inputNumber.replaceAll(',', '.');
return newText;
}
return inputNumber;
}
#override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
return newValue.copyWith(text: replaceCommaWithDot(newValue.text));
}
}
And DecimalTextFormField will return
return TextFormField(
keyboardType: const TextInputType.numberWithOptions(decimal: true),
// how to use replaceCommaWithDot method when onChanged gets called?
inputFormatters: [
CustomFormater(),
],
onChanged: (value) {
if (onChanged != null) onChanged!(value);
},
);
More about TextInputFormatter.
You should better use RegEx. Add an expression to your TextFormField's inputFormatters that will forbid comma. It won't replace it but you just won't be able to write it.
I am building an app that generates form fields from JSON data.
the Form widget is declared in the custom_form.dart
child: Form(
key: _globalKey,
child: Column(
children: [
SizedBox(
height: 10,
),
Text("Register Form: "),
SizedBox(
height: 3,
),
for (var i = 0; i < this.widget.widgetList.length; i++)
generateWidgetFromType(this.widget.widgetList[i]),
I'm using that generateWidgetFrom Type to generate the widgets
Widget generateWidgetFromType(Mywidget mywidget) {
switch (mywidget.type) {
case "CheckBox":
return GenerateCheckBox(mywidget);
case "Input":
return CustomGeneratedWidget(mywidget,
onSaved: (value) => widget.test = value);
case "DatePicker":
return GenerateDatePicker(mywidget);
}
return Text("This type is not supported yet");
}
The TextFormField is declared in the CustomGeneratedWidget
child: TextFormField(
controller: textEditingController,
obscureText: isPasswordField(this.widget.mywidget.key),
keyboardType: customType(this.widget.mywidget.key),
decoration: InputDecoration(
labelText: this.widget.mywidget.label,
border: OutlineInputBorder()),
validator: (value) {
I want to retrieve data from TextFormField in the CustomGeneratedWidget when I click on the Add button in the custom_form.dart
One way might be to add a method called getValue() on to your CustomGeneratedWidget class:
class CustomGeneratedWidget extends Mywidget {
TextEditingController textEditingController = TextEditingController();
...
String getValue() {
return textEditingController.text;
}
...
#override
Widget build(BuildContext context) {
...
}
}
I'm guessing, based on what you're building, that you'll want to eventually get data not just from TextFormField / CustomGeneratedWidget instances, but also instances of GenerateCheckBox and GenerateDatePicker as well. With that being the case, if it were me, I would add an abstract method to Mywidget that you override in its subclasses, perhaps called getValue(). So, Mywidget might look like:
abstract class Mywidget extends Widget {
...
// this method is purposefully unimplemented, and is therefore an "abstract" method
dynamic getValue();
...
}
In your subclasses, such as CustomGeneratedWidget, you would "override" this method by redefining it / implementing it, and therefore making it "concrete":
class CustomGeneratedWidget extends Mywidget {
TextEditingController textEditingController = TextEditingController();
...
#override
String getValue() {
return textEditingController.text;
}
#override
Widget build(BuildContext context) {
return Container(
child: TextFormField(
controller: textEditingController
...
)
);
}
}
Back in custom_form.dart, in your handler for your 'Add' button, you could go through the list of created Mywidget instances and call getValue() on each.
Can I disable input in TextField with open keyboard?
I am trying TextField with readOnly property, but when I set readOnly value true my device keyboard hide. I want do this without hidding keyboard
You can try this
TextField(
readyOnly: true,
showCursor: true,
// ...
),
As for now, you can do this by adding enabled to your TextField.
TextField(
controller: _controller,
enabled: false,
);
One way to do this is like so.
class _MyWidgetState extends State<MyWidget>{
var tc = TextEditingController();
var readOnlyText = 'read only';
#override
void initState() {
super.initState();
tc.text = readOnlyText;
}
#override
Widget build(BuildContext context) {
return TextField(
controller: tc,
onChanged: (_){
tc.text = readOnlyText;
tc.selection = TextSelection.fromPosition(TextPosition(offset: tc.text.length));
},
);
}
}
I can't control keyboard show or hide, In my project I need to always hide keyboard but keep focused to display my custom keyboard(a widget).
This is I want
And this is my problem
To hide keyboard and keep the cursor visible, set readOnly to true and showCursor to true.
TextFormField(
showCursor: true,
readOnly: true),
See flutter/issues/#16863
FYI, TextInputType.none was introduced in #83974:
TextField(
keyboardType: TextInputType.none,
...
)
You can use custom focusNode
This prevents keyboard appearing only on first tap:
TextField(focusNode: FirstDisabledFocusNode(),)
class FirstDisabledFocusNode extends FocusNode {
#override
bool consumeKeyboardToken() {
return false;
}
}
This prevents always:
TextField(focusNode: AlwaysDisabledFocusNode())
class AlwaysDisabledFocusNode extends FocusNode {
#override
bool get hasFocus => false;
}
Insert NoKeyboardEditableText instead your TextField
class NoKeyboardEditableText extends EditableText {
NoKeyboardEditableText({
#required TextEditingController controller,
TextStyle style = const TextStyle(),
Color cursorColor = Colors.black,
bool autofocus = false,
Color selectionColor
}):super(
controller: controller,
focusNode: NoKeyboardEditableTextFocusNode(),
style: style,
cursorColor: cursorColor,
autofocus: autofocus,
selectionColor: selectionColor,
backgroundCursorColor: Colors.black
);
#override
EditableTextState createState() {
return NoKeyboardEditableTextState();
}
}
class NoKeyboardEditableTextState extends EditableTextState {
#override
Widget build(BuildContext context) {
Widget widget = super.build(context);
return Container(
decoration: UnderlineTabIndicator(borderSide: BorderSide(color: Colors.blueGrey)),
child: widget,
);
}
#override
void requestKeyboard() {
super.requestKeyboard();
//hide keyboard
SystemChannels.textInput.invokeMethod('TextInput.hide');
}
}
class NoKeyboardEditableTextFocusNode extends FocusNode {
#override
bool consumeKeyboardToken() {
// prevents keyboard from showing on first focus
return false;
}
}
try use input_with_keyboard_control package
It helped me solve my problem, of receiving the text from a barcode scanner, without showing the keyboard