Is there a way I can set the default TextField textCapitilisation to TextCapitilisation.sentences so that I do not have to add to it every TextField?
Ideally in ThemeData?
Like # F Perroch said, I don't think that is possible too but you can create a Custom TextField for all of your TextField Widgets and use them where appropriate like the exmaple below:
Create a CustomTextField widget like below
class CustomTextField extends StatelessWidget {
/// define property of text fields you want here
final String hinText;
final String labelText;
final Widget icon;
final TextStyle labelStyle;
CustomTextField({this.hinText, this.labelText, this.icon, this.labelStyle});
#override
Widget build(BuildContext context) {
return TextField(
// set your text capitalization here
textCapitalization: TextCapitalization.sentences,
decoration: InputDecoration(
/// set other properties here
hintText: hinText,
labelText: labelText,
labelStyle: labelStyle,
prefixIcon: icon,
),
);
}
}
Call the CustomTextField widget anywhere like below
CustomTextField(
hintText: 'Hello',
labelText: 'Hi there',
labelStyle: TextStyle(....),
icon: Icon(Icons.person)
),
I hope this answers your question.
Related
I'm studying Flutter, so I'm just a newbie.
I tried to create a widget with an optional IconData type parameter in the constructor, but I was getting an error.
I got added "?" in front of the local variable. From then on, I just had to enclose the constructor parameters in "{ }". I've found a way to make it work, but I'm not sure it is the best/correct way to do so.
If you have any tip, I'll be happy to hear it!
That's my code:
class Editor extends StatelessWidget {
final TextEditingController controlador;
final String label;
final String hint;
final IconData? fieldIcon;
Editor(
{required this.controlador,
required this.label,
required this.hint,
this.fieldIcon});
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16.0),
child: TextField(
controller: controlador,
style: const TextStyle(
fontSize: 24.0,
),
decoration: InputDecoration(
labelText: label,
hintText: hint,
icon: fieldIcon != null ? Icon(fieldIcon) : null,
),
),
);
}
}
Your code is correct. Nothing inappropriate in my opinion.
However, I feel the following checking for is redundant:
icon: fieldIcon != null ? Icon(fieldIcon) : null,
Given that the icon property of InputDecoration already takes a nullable icon, why not give it just that?
Maybe change the type of fieldIcon from IconData? to Icon? itself. Then, where you consume the icon in the InputDecoration, simply give it the nullable fieldIcon:
icon: fieldIcon,
But wherever you use this Editor widget, remember to give it an Icon for fieldIcon and not an IconData.
When I set the TextField.prefixIcon property to an Icon(Icons.example) widget, the color of the icon automatically adapts according to the state of the TextField (enabled, focussed, ...).
Now, I got an Icon Pack with svg files that I want to use within the TextField. I am using flutter_svg to show them like that:
TextFormField(
decoration: InputDecoration(
hintText: "Password",
prefixIcon: SvgPicture.asset(
AppIcons.lock,
),
),
),
Now, how can I achieve the automatic color adaption with SvgPicture?
you need to resolve it manually :
FocusNode _focusNode = FocusNode();
bool _enabled = true;
#override
Widget build(BuildContext context) {
return TextFormField(
focusNode: _focusNode,
enabled: _enabled,
decoration: InputDecoration(
hintText: "password"
).copyWith(
prefixIcon: SvgPicture.asset(AppIcons.lock, color: _resolveColor())
),
);
}
Color _resolveColor(){
if (_focusNode.hasFocus){
return Colors.yellow;
}
if(!_enabled){
return Colors.white;
}
if (!_form.valid){
return Colors.red;
}
return Colors.grey;
}
I have 3 TextFormFields, the last one is for the Password, which means it needs a suffixIcon to show/hide the password, if there is no content, the labels show in the center of the fields, which is the needed look:
But as soon as some content is added, the password text gets some padding (the size of the icon is added to the content as padding), like this:
I tried using a Stack, with the TextFormField and an Icon, but if the Icon is on top, the Password field is unclickable, if the Password field is on top, the icon is unclickable.
Does anyone have any idea how to solve this padding thing?
You can try using prefixIcon inside your decoration for your TextFormField.
It would look something like this :
TextFormField(
//all your other widget here
decoration: InputDecoration(
prefixIcon: prefixIcon??Icon(Icons.visibility),
),
),
If you are having trouble with Stack children pressed/tap. Place tappable widget at bottom level of stack.
Here is the password field you can try:
class PassWordFied extends StatefulWidget {
PassWordFied({Key? key}) : super(key: key);
#override
_PassWordFiedState createState() => _PassWordFiedState();
}
class _PassWordFiedState extends State<PassWordFied> {
bool _isVisiblePassword = true;
#override
Widget build(BuildContext context) {
return TextFormField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(15),
// isDense: true, //you can test it
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_isVisiblePassword = !_isVisiblePassword;
});
},
child: Icon(
_isVisiblePassword ? Icons.visibility_off : Icons.visibility,
),
),
fillColor: Colors.white.withOpacity(.7),
filled: true,
labelText: "Password"),
obscureText: _isVisiblePassword,
);
}
}
I am currently testing my Flutter app on both my iPhone 8 and my Android moto G8.
However, the issue I am running into is that while everything works well on my Android moto G8, on my iPhone it seems that whenever I change a TextField the value in the previous TextField becomes null i.e.:
flutter: This is in error: 'package:firebase_auth/src/firebase_auth.dart': Failed assertion: line 174 pos 12: 'email != null': is not true.
But When I was typing on the device the printout is:
flutter: This is in email:test#gmail.com, value: test#gmail.com
Here is the code for my custom textfield:
class InputTextFields extends StatefulWidget {
InputTextFields({this.title, this.obscureText, this.setValue});
final String title;
final bool obscureText;
Function setValue;
final TextEditingController _controller = TextEditingController();
#override
_InputTextFieldsState createState() => _InputTextFieldsState();
}
class _InputTextFieldsState extends State<InputTextFields> {
#override
Widget build(BuildContext context) {
String hintText;
return Container(
padding: EdgeInsets.only(bottom: 10, left: 35, right: 35),
child: TextField(
obscureText: widget.obscureText,
decoration: InputDecoration(
labelText: widget.title,
labelStyle: TextStyle(
fontFamily: 'Montserrat',
fontWeight: FontWeight.bold,
color: Colors.grey),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.grey,
),
),
hintText: hintText,
),
onChanged: widget.setValue,
),
);
}
}
So I am sure the TextField is working as intended but the error still persists. Any ideas how I can solve this?
The problem seems to be from your onChanged: widget.setValue in your TextField. Your function is making the previous TextField null. The best way to retrieve the value of a TextField is to use a TextEditingController. In order to use a TextEditingController in your custom TextField, you would have to pass it as a parameter.
class InputTextFields extends StatefulWidget {
InputTextFields({this.title, this.obscureText, this.controller});
final String title;
final bool obscureText;
final TextEditingController controller;
}
In your TextField:
controller:widget.controller
This is how you use that new custom TextField:
final TextEditingController myController=TextEditingController();
InputTextFields(title:"Test",obscureText:false,controller:myController),
I think you are trying to validate if the TextField's value is an email or not. You could easily check it by using RegExp or by using https://pub.dev/packages/email_validator package. You could also use TextFormField instead of TextField to check if the TextField's value is null. Have a look at this: https://flutter.dev/docs/cookbook/forms/validation. Good Luck!
In Flutter, inputDecoration's countertext property does not change as the user is typing in the TextFormField. Is it possible to decrement the countertext as the user is typing?
TextFormField(
keyboardType: TextInputType.number,
decoration: new InputDecoration(
counterText: "9",
hintText: "Enter exact order number",
),
)
I edit this answer to work with your question
class StackEditText extends StatefulWidget {
#override
_StackEditTextState createState() => _StackEditTextState();
}
class _StackEditTextState extends State<StackEditText> {
TextEditingController _controller = new TextEditingController();
void onValueChange() {
setState(() {
_controller.text;
});
}
#override
void initState() {
super.initState();
_controller.addListener(onValueChange);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: TextFormField(
controller: _controller,
maxLength: 9,
decoration: InputDecoration(
counterText: "${9 - _controller.text.length}",
hintText: 'Enter exact order number',
),
),
),
);
}
}
I do not recommend using the decoration: InputDecoration::counterText. You have to use setState or whatever to manually update the counter that way.
Instead, I recommend the maxLength property, that automatically makes a counter and updates it:
TextField(maxLength: 8)
Result:
This might be what most people want.
You can even further customize it with the buildCounter parameter, to return whatever widget you want when the text length changes. For example, if you only want to display how many characters left, you can do this:
TextField(
maxLength: 8,
buildCounter: (
BuildContext context, {
int currentLength,
int maxLength,
bool isFocused,
}) {
return Text('${maxLength - currentLength}');
},
)