I have a question.
I have an application with various forms with textfields.
In each form i noted that when i use tab button to switch fields, focus disappear from the fields and goes i dont know where.
I tried to use Focus widget to see if on tab the focus change, and it doesn't (only when the focus return to the first field, Focus return me that it is changed)
Someone could help me? Thanks you
This is a snippet of Login form
Focus(
onFocusChange: ((value) => print("focus is changed")),
child: Column(
children: [
Semantics(
value: "Email",
child: TextFormField(
key: Key("Email"),
validator: (value) => emailValidator(value),
controller: _emailController,
),
),
const SizedBox(height: 20),
Semantics(
value: "Password",
child: TextFormField(
key: Key("Password"),
validator: (value) =>
formRequiredValidation("password", value),
textInputAction: TextInputAction.done,
obscureText: _isTypePassword,
controller: _passwordController,
onChanged: (value) {
setState(() {});
},
onFieldSubmitted: (String value) => _onSubmit(),
),
),
const SizedBox(height: 20),
SizedBox(
width: double.infinity,
height: 45,
child: ElevatedButton(
key: Key("Accedi"),
onPressed: _onSubmit,
child: const Text(
"ACCEDI",
),
),
),
const SizedBox(height: 20),
GestureDetector(
onTap: () {},
child: Text(
"Hai dimenticato la password?",
style: TextStyle(
color: Theme.of(context).primaryColor),
),
),
const SizedBox(height: 20),
GestureDetector(
onTap: () {},
child: Text(
"Non sei ancora registrato?",
style: TextStyle(
color: Theme.of(context).primaryColor),
),
),
],
),
),
Good morning,
we solved the problem by deleting the web folder and having it recreate in flutter.
We noticed that the new generated index.html file contains a third of the code compared to the old one.
It should be noted that the project started with Flutter 2 and was subsequently upgraded to Flutter 3.
Also note that with Flutter 3 important improvements have been released for the web part, including the ability to set up a loading page before starting the app or before loading it, along with other things.
Since it wasn't there in Flutter 2, we created a loading page ourselves.
it is our opinion that these changes resulted in the focus on objects not working.
Thanks to all for the precious collaboration.
Related
I have the following form to post data to api. the form has textfields and dropdownbuttons as follows. How can I map to the API and post to api?
Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 50.0),
child: Form(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
TextFormField(
decoration: InputDecoration(hintText: 'Job Title'),
controller: titleController,
onChanged: (val) {},
),
SizedBox(height: 20.0),
TextFormField(
decoration: InputDecoration(hintText: 'Company'),
controller: companyController,
onChanged: (val) {},
),
DropdownButton(
value: currentValue,
icon: const Icon(Icons.keyboard_arrow_down),
items: <String>[
"1",
"2",
"3",
].map((String i) {
return DropdownMenuItem(
value: i,
child: Text(i),
);
}).toList(),
onChanged: onChangedCallback,
),
SizedBox(height: 20.0),
DropdownSearch<String>(
mode: Mode.MENU,
showSearchBox: false,
showClearButton: true,
items: ["Aviation", "Arts", "Business"],
dropdownSearchDecoration: InputDecoration(
labelText: "Category",
hintText: "Select Job Category",
),
onChanged: print,
),
SizedBox(height: 20.0),
TextFormField(
decoration: InputDecoration(hintText: 'Location'),
onChanged: (val) {},
),
SizedBox(height: 20.0),
TextFormField(
maxLines: 3,
decoration: InputDecoration(hintText: 'Description'),
onChanged: (val) {},
),
SizedBox(height: 20.0),
TextFormField(
decoration: InputDecoration(hintText: 'Salary'),
onChanged: (val) {},
),
SizedBox(height: 30.0),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Color.fromARGB(255, 252, 114, 2)),
onPressed: () {
},
child: Text(
"Add",
style:
TextStyle(fontSize: 17, fontWeight: FontWeight.bold),
)),
],
),
),
),
),
I want the textfields to get data and post to api while dropdownbuttons have an item and post the item with the corresponding item name on the api? (Like from the following dropdown buttton DropdownButton( value: currentValue, icon: const Icon(Icons.keyboard_arrow_down), items: <String>[ "1", "2", "3", ].map((String i) { return DropdownMenuItem( value: i, child: Text(i), ); }).toList(), onChanged: onChangedCallback, ),
if I select 1, it will post 1 to the api and the same for category. How can this be implmented? )
First of all you need to use an HTTP client package like Dio or tttp
Then you will need to make an api call using this package whenever you click the button.
So an example using Dio package would be like that
import 'package:dio/dio.dart';
void postHttp() async {
try {
var response = await Dio().post('your-api-link',data: {'title': "job title field", 'currentValue': 'current value field'});
print(response);
} catch (e) {
print(e);
}
}
And you will find more info in the package documentation.
Quick hint:
try to test your api using postman first to make sure it works correctly
I'm trying to implement this view.
I got very close except the smaller dollar sign, now I'm using text mask and appending the dollar sign, but of course, it has same font size view rest of the view
Here is the code
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(width: 8),
IconButton(
icon: Image.asset("assets/images/minus.png"),
onPressed: () => {},
),
Expanded(
child: TextFormField(
controller: controller,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
textAlign: TextAlign.center,
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold, color: kSecondaryColor),
decoration: new InputDecoration.collapsed(hintText: ''),
),
),
IconButton(
icon: Image.asset("assets/images/plus.png"),
onPressed: () => {},
),
SizedBox(width: 8),
],
),
Would be easy to do if I can change the font size of the first character of the TextField or maybe I should use different widget for only dollar sign, but I couldn't manage it to place it inside Expanded.
leadingIcon property of TextFormField puts the sign to beginning of the field, so symbol doesn't follow the text it just stays there, so that it didn't work for me.
prefixText property is also puts the text far away from actualy numbers like this, if I can fix that, that also works.
Update
You need to get rid of Expanded as it won't push the prefix widget with your text. There are other ways to achieve the same effect. You can use Flexible instead to allow TextFormField to be only as big as it needs to be. InputDecoration has a prefix: property that is not available under the .collapsed constructor, so you can remove the border using InputBorder.none instead. Overall you need to make the following changes:
Row(
children: [
SizedBox(width: 8),
IconButton(
icon: Icon(Icons.add),
onPressed: () => {},
),
Spacer(), //<-- This is what I've been telling to add
Flexible( //<-- Change Expanded to Flexible
child: TextFormField(
initialValue: '234',
style: TextStyle(
fontSize: 48,
fontWeight: FontWeight.bold,
color: Colors.purple,
),
decoration: InputDecoration( //<-- Removed collapsed factory constructor
border: InputBorder.none, //<-- Use this to remove the border
prefix: Text( //<-- This is your actual prefix Widget
"\$",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.purple,
),
),
),
),
),
Spacer(), //<-- This is what I've been telling to add
IconButton(
icon: Icon(Icons.add),
onPressed: () => {},
),
SizedBox(width: 8),
],
),
);
This is the final output
Would wrapping the TextFormField inside a Row, along with Text widget to hold $ help?
Also take care to put MainAxisSize.min, so that both the widgets stay together.
Update
Putting up the code, do not wrap Expanded, bring the changes inside child of Expanded. I have added 4 comments, which are the changes you will need to bring in.
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(width: 8),
IconButton(
icon: Icon(Icons.remove),
onPressed: () => {},
),
Expanded(
//1. Intrinsic height is used to place so that its child ROW doesn't take // the whole height
child: IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
// 2. This alignment will align $ with the bottom of textfield.
alignment: Alignment(0.0, 0.5),
child: Text(
"\$",
style: TextStyle(
//3. dollar symbol to have a different font size.
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue),
),
),
SizedBox(
//4. You might need to change the width here, this is the width available //for TextFormField. Logic used here is
//half of the (available screen width - size of the icons at left n right)
width: ((MediaQuery.of(context).size.width - 48) / 2),
child: TextFormField(
// controller: controller,
keyboardType: TextInputType.number,
// inputFormatters: [FilteringTextInputFormatter.digitsOnly],
// textAlign: TextAlign.center,
style: TextStyle(
fontSize: 48,
fontWeight: FontWeight.bold,
color: Colors.blue),
decoration: new InputDecoration.collapsed(hintText: ''),
),
),
]),
),
),
IconButton(
icon: Icon(Icons.add),
onPressed: () => {},
),
SizedBox(width: 8),
],
),
I'm new to flutter, and right now I'm trying to do something similar to this:
img 1.
Where the textformfield is aligned inline with the checkbox, and the checkbox is shrunk at the corner, but the max that I can do is this:
img 2.
Where the checkbox is filling half of the screen, I've tried to expand the textformfield in several ways, like sizedbox, flex and expand, but none of then made the checkbox shrink to the corner and the textformfield expand, the line is always split in the middle.
The actual row code looks like this:
Row(
children: [
Expanded(
child: TextFormField(
style: TextStyle(
fontSize: 20
),
decoration: InputDecoration(
hintText: "Senha",
),
autocorrect: false,
obscureText: true,
),
),
Flexible(
child: SizedBox(
width: 10,
child: Checkbox(value: true, onChanged: (value){}),
)
)
],
),
Is there any way for me to do this?
Do I have to use a container or something like that?
Any help would be appreciated.
You can use CheckboxListTile class.
CheckboxListTile(
title: const Text('Title'),
value: value,
onChanged: (value) {
print(value);
},
);
let me know if it work for you.
I've managed to do it using flex property, as the following code shows:
Row(
children: [
Expanded(
flex: 11,
child: TextFormField(
style: TextStyle(
fontSize: 20
),
decoration: InputDecoration(
hintText: "Usuario",
),
autocorrect: false,
obscureText: true,
),
),
Flexible(
child: SizedBox(
width: 10,
child: CheckboxListTile(
value: true,
onChanged: (value) {
},
),
)
)
],
),
I have an ExpansionTile with a TextField inside and trying to set the focus to this text field when user expands the tile. But for some reasons I can't get it working.
Here is the code:
ExpansionTile(
key: PageStorageKey<String>("notes_key"),
title: Text(
"Notes",
style: TextStyle(color: Colors.indigo),
),
onExpansionChanged: (expanded){
if(expanded){
FocusScope.of(context).requestFocus(_notesFocusNode);
_notesController.value = _notesController.value.copyWith(text: _notes);
} else {
_notesFocusNode.unfocus();
}
},
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
),
textInputAction: TextInputAction.newline,
style: TextStyle(color: Colors.black),
keyboardType: TextInputType.multiline,
focusNode: _notesFocusNode,
controller: _notesController,
key: PageStorageKey("notes_field_key"),
minLines: 1,
maxLines: null,
onChanged: (value) => _notes = value,
),
),
IconButton(
icon: Icon(Icons.done),
color: Colors.teal,
onPressed: () => _notesFocusNode.unfocus(),
),
],
),
],
)
Any help appreciated.
For a bigger context, the text field is not inside any form. The provided piece of code lays inside the bigger one, where it is wrapped in the ListView. Probably I need to have some parent focus scope in my view?
The TextFormField is not yet available to get Focus when you expand the Tile. It only becomes available after a few milliseconds of the animation starting. Since you don't have a way to know when the animation has finished, you can make a workaround by adding a delay. I would advise a minimum of 200 milliseconds so that the animation doesn't stagger but the TextFormField gets focus:
Future.delayed(Duration(milliseconds: 200), (){
FocusScope.of(context).requestFocus(_notesFocusNode);
});
I'm learning to code in Flutter and and redoing one of my Android/iOS apps. This is roughly what the UI looks like so far:
When I tap a field to open the keyboard, it smashes all of the fields together.
I'm trying to decide what the best way of handling this is. The only way I can think of to fix it is to somehow not have all of the fields and the button pushed up when the keyboard opens. But if I do that, then the fields lower on the screen will not be visible when data is being entered into them. Is there a good way to handle this?
This is the code for this view:
class _CarbCalcState extends State<CarbCalc> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Carb Calculator'),
backgroundColor: Colors.purple.shade700,
leading: IconButton(
icon: Icon(Icons.settings),
onPressed: () {},
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.library_books),
onPressed: () {},
)
],
),
body: Container(
margin: EdgeInsets.only(top: 40.0, left: 20.0, right: 20.0),
child: Column(
children: <Widget>[
NutrientValue(
nutrientName: 'Protein',
onChanged: (value) {
print('Protein Changed');
},
),
NutrientValue(
nutrientName: 'Fat',
onChanged: (value) {},
),
NutrientValue(
nutrientName: 'Fiber',
onChanged: (value) {},
),
NutrientValue(
nutrientName: 'Moisture',
onChanged: (value) {},
),
NutrientValue(
nutrientName: 'Ash',
onChanged: (value) {},
),
SizedBox(
height: 30.0,
),
ButtonTheme(
minWidth: double.infinity,
height: 50,
child: FlatButton(
onPressed: () {},
color: Colors.blue.shade700,
child: Text(
'Calculate Carbs',
style: TextStyle(
fontSize: 20,
),
),
),
),
],
),
),
);
}
}
class NutrientValue extends StatelessWidget {
NutrientValue({#required this.nutrientName, #required this.onChanged});
final String nutrientName;
final Function onChanged;
#override
Widget build(BuildContext context) {
return Expanded(
child: Row(
children: <Widget>[
Container(
width: 90,
child: Text(
nutrientName,
style: TextStyle(fontSize: 18.0),
),
),
Expanded(
child: TextField(
keyboardType: TextInputType.numberWithOptions(
signed: false,
decimal: true,
),
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
onChanged: this.onChanged,
decoration: InputDecoration(
hintText: 'Enter $nutrientName',
hintStyle: TextStyle(
color: Colors.grey,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0),
),
borderSide: BorderSide.none,
),
filled: true,
fillColor: Colors.white,
),
),
),
],
));
}
}
You are having a Column with several Expanded inside which take care that the space is evenly distributed. When the space shrinks by the keyboard, they move together. Basically it is a good idea to put input fields into a Scrollview because of the Keyboard. You can use SingleChildScrollView with your Column but you need to replace the Expanded widgets with a Container for example or just use the plain TextFields.