Flutter: suffixIcon making text not centered - flutter

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

Related

TextField keeps old value

I have an issue with a textfield in flutter.
I need to get a town or postal code to redirect the user to another page. But it seems like I keep old value even if the text inside textfield changes.
I tried to clear it, make conditions but I don't understand why the text does not keep the current value.
Here some code :
Check if it's Paris, for the borough
#override
void initState() {
editingController.addListener((){
setState(() {
if(editingController.text.isEmpty) {
editingController.clear();
isParis = false;
}
});
});
super.initState();
}
Button which redirect, the method getPcFromQuery (it's an async method) retrieve data relatives to a town name.
RaisedButton(
onPressed: (){
print(editingController.text);
getPCFromQuery(editingController.text)
.then((town) {city = town.featureName; postalCode = town.postalCode;});
setState(() {
if(city.toString().toLowerCase() == "paris")
isParis = true;
else
isParis = false;
});
print("postalCode : $postalCode");
postalCode != null && city.toString().toLowerCase() != "paris"?
Navigator.of(context).push(MaterialPageRoute(builder: (context) => PreferencesPage(postalCode: postalCode))) :
Container(child: Text(""));
})
But when I click on the next button (I need to click on it two times to make it work) and when I change the value inside my textfield, it keeps the previously entered value.
Do you know where it can come from?
This is TextField built:
class SearchBar extends StatelessWidget {
const SearchBar({
Key key,
#required this.editingController,
}) : super(key: key) ;
final TextEditingController editingController;
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(10.0)),
child: TextField(
controller: editingController,
decoration: InputDecoration(
hintText: AppStrings.searchTown,
hintStyle: GoogleFonts.notoSans(fontSize: 14.0),
border: InputBorder.none,
fillColor: Colors.grey.withOpacity(0.5),
prefixIcon: Icon(Icons.search, color: Colors.grey)
),
)
);
}
}
And method _getPcFromQuery :
_getPCFromQuery(String city) async {
var addresses = await Geocoder.local.findAddressesFromQuery(city);
var first = addresses.first;
print(first.featureName);
print(first.addressLine);
return first;
}
The weird thing is, when I try the first time, the prints inside _getPcFromQuery method get text, but the print "print("postalCode : $postalCode");" on the onPressed method button is null.
Specify the key parameter for TextField.
class SearchBar extends StatelessWidget {
const SearchBar({
Key key,
#required this.editingController,
}) : super(key: key) ;
final TextEditingController editingController;
final searchKey = GlobalKey(); // <-- create a global key
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(10.0)),
child: TextField(
key: searchKey, // <-- specify the declared key here
controller: editingController,
decoration: InputDecoration(
hintText: AppStrings.searchTown,
hintStyle: GoogleFonts.notoSans(fontSize: 14.0),
border: InputBorder.none,
fillColor: Colors.grey.withOpacity(0.5),
prefixIcon: Icon(Icons.search, color: Colors.grey)
),
)
);
}
}

Flutter: Set default TextField property across the whole app

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.

Flutter enabled and focus textformfield

I create a profile page and i have 4 textformfield. I want to on tap icon activate textformfield and focus at the same time. Now I need tap twice on icon and first activated field, secondly focused.
How to solve it?
My code:
class UserProfile extends StatefulWidget {
#override
_UserProfileState createState() => _UserProfileState();
}
class _UserProfileState extends State<UserProfile> {
FocusNode myFocusNode;
bool isEnable = false;
#override
void initState() {
super.initState();
myFocusNode = FocusNode();
}
#override
void dispose() {
myFocusNode.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.fromLTRB(40.0, 50.0, 20.0, 0.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Flexible(
child: TextFormField(
enabled: isEnable,
focusNode: myFocusNode,
),
),
IconButton(
icon: Icon(Icons.edit),
onPressed: () {
setState(() {
isEnable = true;
FocusScope.of(context).requestFocus(myFocusNode);
});
})
],
),
You should use autofocus: isEnable instead.
just do like below in your ontap
setState(() {
if(isEnable)
Future.delayed(const Duration(milliseconds: 10), ()
{FocusScope.of(context).requestFocus(myFocusNode);
});
isEnable = true;
});
in first time isEnable is false so focusing not call and just enabling work and in other times get focus too.
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.
Try using readOnly instead of enabled in TextFormField
I faced similar issue when I had multiple TextFields to enable kinda PIN input. And some of that had to be dynamically enabled and disabled plus prevent users from entering value in the next field while they haven't finished the previous one. I've tried a lot of approaches and focusing field after some delay was not a way to go because I wanted the keyboard to always be available while entering. So I've took a crazy path and solved this next way:
onTap: () => _focusNodes[_currentLetterIndex].requestFocus()
where _focusNodes are for each letter and _currentLetterIndex is calculated programmatically during input (when finished letter 0 -> current becomes 1 and so on). As the result when user tried to tap on next field - it was automatically refocused to the current one which behaves like the next field is disabled.
An example of the full text field looks like this (don't pay attention to decorations etc.)
TextField(
key: ValueKey(index),
controller: _editingControllers[index],
onTap: () => _focusNodes[_currentLetterIndex].requestFocus(),
focusNode: _focusNodes[index],
textAlign: TextAlign.center,
showCursor: false,
maxLength: 2,
enableInteractiveSelection: false,
autocorrect: false,
enableSuggestions: false,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
height: 1.2,
decoration: TextDecoration.none),
decoration: InputDecoration(
fillColor: !_wordCompleted &&
!correct &&
_editingControllers[index].text.isNotEmpty
? const Color(0xFFFFEEF0)
: Colors.white,
filled: !correct,
counterText: "",
border: defaultInputBorder,
focusedBorder: !correct &&
!_wordCompleted &&
_editingControllers[index].text.isNotEmpty
? incorrectInputBorder
: focusedInputBorder,
enabledBorder: _wordCompleted
? focusedInputBorder
: correct
? correctInputBorder
: defaultInputBorder,
errorBorder: defaultInputBorder,
disabledBorder: _wordCompleted
? focusedInputBorder
: correct
? correctInputBorder
: defaultInputBorder,
contentPadding: const EdgeInsets.only(left: 2)),
),

Flutter Why my textfield lose the value when I dont focus on it?

I made a class and it has a controller and a widget that includes a padding within a textfield.
Now when I change the focus from the textfield to something else it lose the value.
this is my code.
`
class RxInput {
final String hindText;
final bool obscureText;
Widget widget;
final TextEditingController controller = new TextEditingController ();
String get value => controller.text;
RxInput (this.hindText,context,{this.obscureText = false}) {
widget = Padding (
padding: const EdgeInsets.all(20.0),
child: Material(
borderRadius: BorderRadius.circular(20.0),
shadowColor: Colors.blue.shade200,
elevation: 5.0,
child:TextField(
controller: controller,
decoration: InputDecoration(
hintText: hindText,
border: InputBorder.none,
alignLabelWithHint: true,
),
obscureText: obscureText,
)
),
);
}
}
`
I solved this question. You should initialize your variable in the initState instead of build.

Text in the TextField disappears when keyboard is removed

Text entered in my TextField widget disappears when I remove the keyboard from the view.
There are two TextField's, title and description. The above problem only occurs for the title but not with the description.
Here's the relevant excerpt from the build method:
#override
Widget build(BuildContext context) {
_note = widget._note; // This is coming from StatefulWidget Class above
TextStyle textStyle = Theme.of(context).textTheme.title;
_titleController.text = _note.title;
_descriptionController.text = _note.description;
return Scaffold(
body: ListView(
children: <Widget>[
Padding(
padding: EdgeInsets.all(15.0),
child: TextField(
style: textStyle,
controller: _titleController,
decoration: InputDecoration(
labelText: "Title",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
),
),
Padding(
padding: EdgeInsets.all(15.0),
child: TextField(
style: textStyle,
controller: _descriptionController,
decoration: InputDecoration(
labelText: "Description",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
),
),
...
}
}
Screenshots of Keyboard shown & removed.
This occurs because you are setting the text in your build method. This build method can get invoked at any time, e.g. when the keyboard is contracted because the UI needs to react to that.
This means that you should move this code to initState:
#override
void initState() {
_note = widget._note;
_titleController.text = _note.title;
_descriptionController.text = _note.description;
super.initState();
}
initState is only called once when the your widget is inserted into the build tree.
I am not sure why this only happens with one of the TextFields's. I assume that you are using the TextController's somewhere else to set the Note's content, which could cause this behavior.
Furthermore, you should probably avoid using a leading underscore _ for _note in your StatefulWidget (widget._note) as you access it from your State.