How to have a unique error message for two textfields - flutter

Hi I have a little problem since a few days... I'm trying to find out how to make two fields display an error message at the same place.
I tried with a Formfield but it bugs me because the second textformfield falls in error since I have only one state. I also tried with a simple Formfield but I can't set my validator message in a variable and then display it in a padding.
Would you have an idea please?
Thanks in advance.
Example : I would like to display my error message instead of the Text widget "Error message".

I managed to solve your problem.
Take a look at this screenshot and code:
Screenshot -
Code:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _errorText = '';
final GlobalKey<FormState> _key = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Form(
key: _key,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 100,
width: 50,
child: TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
setState(() {
_errorText = 'Please enter some text';
});
}
return null;
},
),
),
const SizedBox(
width: 50,
),
SizedBox(
height: 100,
width: 50,
child: TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
setState(() {
_errorText = 'Please enter some text';
});
}
return null;
},
),
),
],
),
),
Text(_errorText),
ElevatedButton(
onPressed: () {
if (_key.currentState!.validate()) {}
},
child: const Text('Submit'),
),
],
),
),
),
);
}
}

Related

Can't align TextField/Form to center when decreasing its width

I am trying to change the width of the text field, while also keeping it centered, I found a way to decrease its sized by wrapping it in a sized box and setting the width, however that seems to make it unaligned to the center, and when I try to align it again with the Center() property or the Align() Property nothing works.
import 'package:flutter/material.dart';
import 'package:qr_flutter/qr_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(),
home: Scaffold(body: MyCustomForm()),
debugShowCheckedModeBanner: false,
);
}
}
class MyCustomForm extends StatefulWidget {
const MyCustomForm({super.key});
#override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
// Create a corresponding State class.
// This class holds data related to the form.
class MyCustomFormState extends State<MyCustomForm> {
// Create a global key that uniquely identifies the Form widget
// and allows validation of the form.
//
// Note: This is a GlobalKey<FormState>,
// not a GlobalKey<MyCustomFormState>.
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
// Build a Form widget using the _formKey created above.
return Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Submit'),
),
],
),
);
}
}
You need to wrap your column with SizedBox and set its width to screen size. now when you set width for textfield its look ok, like this:
SizedBox(
width: double.infinity,//<--- add this
child: Form(
key: _formKey,
child: Column()
...
)
full example:
SizedBox(
width: double.infinity,
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 200,
child: TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
),
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Submit'),
),
],
),
),
)
Try below code and set width of SizedBox double.infinity :
SizedBox(
width: double.infinity,
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: const Text('Submit'),
),
],
),
),
)
Actually when you wrap TextFormField inside SizedBox your column width also becomes exactly equal to the width you gave to the SizedBox. This is because the column's width depends on the widest child inside of it. That is why you are not able to align or center the TextFormField.
Just wrap your Column inside the Center widget and your column will take all the width available and the children will also align to the center.
Form(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 100,
child: TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
),
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {},
child: const Text('Submit'),
),
],
),
),
)

create field for load images

I have a code that outputs fields for the user to fill in (code below. I have shortened it here for ease of reading.). I would like to add one more field to this form, which can upload various photos from the phone gallery (preferably with the ability to delete a photo if the user made a mistake when choosing). How can I implement this?
class FormForDeviceService extends StatefulWidget {
#override
State<StatefulWidget> createState() => _FormForDeviceService();
}
class _FormForDeviceService extends State {
final _formKey = GlobalKey<FormState>();
Widget build(BuildContext context) {
return Container(padding: const EdgeInsets.all(10.0),
child: Form(key: _formKey, child: Column(children: <Widget>[
new Text('What is problem', style: TextStyle(fontSize: 20.0),),
new TextFormField(decoration: const InputDecoration(
hintText: 'Describe the problem',),
ElevatedButton(
onPressed: (){if(_formKey.currentState!.validate()) {_formKey.currentState?.reset();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Form completed successfully', style: TextStyle(color: Colors.black),),
backgroundColor: Colors.yellow,));
}},
child: const Text('Submit', style: TextStyle(color: Colors.black),),
style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.yellow)),)
],)));
}
}
Page at the moment
my expectations (or something similar)
An another approach is here-
(I have made a separate widget to handle all these things and you just need to attach it in any scrollable widget)
my code is as follow:
Main Code with that custom widget:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_memory/image_picker_widget.dart';
void main() {
runApp(GetMaterialApp(title: 'Flutter', home: Flutter()));
}
class Flutter extends StatefulWidget {
const Flutter({Key? key}) : super(key: key);
#override
State<Flutter> createState() => _FlutterState();
}
class _FlutterState extends State<Flutter> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter'),
centerTitle: true,
),
body: Center(
child: Column(
children: [
//This is the widget I am talking about
ImagePickerWidget()
],
),
),
);
}
}
And now the code for that custom widget:
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class ImagePickerWidget extends StatefulWidget {
const ImagePickerWidget({Key? key}) : super(key: key);
#override
State<ImagePickerWidget> createState() => _ImagePickerWidgetState();
}
class _ImagePickerWidgetState extends State<ImagePickerWidget> {
late List<CustomImage> images;
late double size;
late ImagePicker imagePicker;
late int idGenerator;
#override
void initState() {
images = [];
size = 100;
idGenerator = 0;
imagePicker = ImagePicker();
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
pickImage();
},
child: Text('Pick Image')),
Wrap(
children: images.map((image) {
return Stack(children: [
SizedBox(
height: size,
width: size,
child: ClipRRect(
child: Image.memory(
image.imageData,
fit: BoxFit.fill,
))),
Positioned(
right: 4,
top: 4,
child: InkWell(
onTap: () {
//delete image
images.removeWhere(
(element) => element.imageData == image.imageData);
setState(() {});
},
child: Container(
color: Colors.white, child: Icon(Icons.clear))))
]);
}).toList())
],
);
}
Future<void> pickImage() async {
// XFile? image = await imagePicker.pickImage(source: ImageSource.camera);
XFile? image = await imagePicker.pickImage(source: ImageSource.gallery);
if (image != null) {
Uint8List imageData = await image.readAsBytes();
int id = idGenerator++;
images.add(CustomImage(imageData: imageData, id: id));
setState(() {});
}
}
}
class CustomImage {
Uint8List imageData;
int id;
CustomImage({required this.imageData, required this.id});
}
You can customize the widget in order to use the images list of that widget or you can simply pass the callbacks for that.
we store file here your can use path(string) instead file
List<File> myfile = [];
image_picker package used here to pick image
image_picker: ^0.8.4+10
call like this in your code
Container(
height: 200,
padding: EdgeInsets.all(4),
child: PickPhoto())
Pick photo widget
class PickPhoto extends StatefulWidget {
const PickPhoto({Key? key}) : super(key: key);
#override
State<PickPhoto> createState() => _PickPhotoState();
}
class _PickPhotoState extends State<PickPhoto> {
#override
Widget build(BuildContext context) {
return Material(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
width: 45,
height: 45,
child: ElevatedButton(
onPressed: () async {
var file =
await picker?.pickImage(source: ImageSource.gallery);
setState(() {
myfile.add(File(file!.path));
});
},
child: Text("Add Photo"))),
),
Expanded(
child: ListView.builder(
// physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: myfile.length,
itemBuilder: (context, index) => Container(
padding: EdgeInsets.all(4),
height: 175,
width: 125,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Align(
alignment: Alignment.topRight,
child: IconButton(
onPressed: () {
setState(() {
myfile.removeAt(index);
});
},
icon: Icon(Icons.close),
),
),
Expanded(
child: Container(
child: myfile[index] == null
? Text("")
: Image.file(
myfile[index],
fit: BoxFit.fill,
),
),
),
],
),
)),
)
],
),
);
}
}
SampleCode
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
ImagePicker? picker;
void main() {
WidgetsFlutterBinding.ensureInitialized();
picker = ImagePicker();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MySQL Test',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [FormForDeviceService()],
),
);
}
}
List<File> myfile = [];
List<int> f = [1, 2, 3, 4, 5];
List<bool> fs = [false, false, false, true, true];
class FormForDeviceService extends StatefulWidget {
#override
State<StatefulWidget> createState() => _FormForDeviceService();
}
class _FormForDeviceService extends State {
final _formKey = GlobalKey<FormState>();
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(10.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
new Text(
'What is problem',
style: TextStyle(fontSize: 20.0),
),
new TextFormField(
decoration: const InputDecoration(
hintText: 'Describe the problem',
),
),
Container(
height: 200,
padding: EdgeInsets.all(4),
child: PickPhoto()),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState?.reset();
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
'Form completed successfully',
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.yellow,
));
}
},
child: const Text(
'Submit',
style: TextStyle(color: Colors.black),
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.yellow)),
)
],
)));
}
}
class PickPhoto extends StatefulWidget {
const PickPhoto({Key? key}) : super(key: key);
#override
State<PickPhoto> createState() => _PickPhotoState();
}
class _PickPhotoState extends State<PickPhoto> {
#override
Widget build(BuildContext context) {
return Material(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Container(
width: 45,
height: 45,
child: ElevatedButton(
onPressed: () async {
var file =
await picker?.pickImage(source: ImageSource.gallery);
setState(() {
myfile.add(File(file!.path));
});
},
child: Text("Add Photo"))),
),
Expanded(
child: ListView.builder(
// physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: myfile.length,
itemBuilder: (context, index) => Container(
padding: EdgeInsets.all(4),
height: 175,
width: 125,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Align(
alignment: Alignment.topRight,
child: IconButton(
onPressed: () {
setState(() {
myfile.removeAt(index);
});
},
icon: Icon(Icons.close),
),
),
Expanded(
child: Container(
child: myfile[index] == null
? Text("")
: Image.file(
myfile[index],
fit: BoxFit.fill,
),
),
),
],
),
)),
)
],
),
);
}
}

Flutter - Validating User Input

So I'm trying to create a sign up page for my app in flutter. So far, I've got some welcome text and an input form where users can input their email. I've also got a button which will eventually change the page underneath the input field that says 'next'. The idea is to have the button disabled which was simple enough to do (just added OnPressed: null) however when the user enters at least one character, followed by an '#' and then a string list of '.com,.co.uk e.t.c) the next button will become enabled. I have tried to add a validate if else statement to the form but to no joy so have removed it from the code below. I guess what I'm asking is how do I:
Validate the input meets my requirements
Disable the button if it does not
Enable the button if it does
All responses / contributions to any of the above are greatly appreciated!
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(MyApp());
}
class MyCustomForm extends StatefulWidget {
#override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
class MyCustomFormState extends State<MyCustomForm> {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(children: <Widget>[
TextFormField(
decoration: InputDecoration(labelText: 'Enter your email'),
),
]),
);
}
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test Bench',
home: Stack(
children: [
Scaffold(
body: Container(
width: double.infinity,
decoration: BoxDecoration(color: Colors.pinkAccent),
child: Padding(
padding: const EdgeInsets.all(30.0),
child: Column(
children: [
Text(
"Hello, Let's Get Started...\n",
style: TextStyle(
fontSize: 60.0,
fontWeight: FontWeight.bold,
fontFamily: 'Oswald',
color: Colors.black,
),
),
MyCustomForm(),
ButtonTheme(
minWidth: 250.0,
child: RaisedButton(
onPressed: null,
child: Text("Next"),
),
),
],
),
),
),
),
],
),
);
}
}
Here is a possible solution. I used regex to validate the email entered.
You can learn more about validation from here:
https://flutter.dev/docs/cookbook/forms/validation
class MyApp extends StatefulWidget {
// This widget is the root of your application.
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _formKey = GlobalKey<FormState>();
bool isValidated = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test Bench',
home: Stack(children: [
Scaffold(
body: Container(
width: double.infinity,
decoration: BoxDecoration(color: Colors.pinkAccent),
child: Padding(
padding: const EdgeInsets.all(30.0),
child: Column(children: [
Text("Hello, Let's Get Started...\n",
style: TextStyle(
fontSize: 60.0,
fontWeight: FontWeight.bold,
fontFamily: 'Oswald',
color: Colors.black,
)),
Form(
key: _formKey,
child: Column(children: <Widget>[
TextFormField(
onChanged: (input) {
_formKey.currentState.validate();
},
validator: (input) {
var regex = RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+");
if (!regex.hasMatch(input) && isValidated) {
setState(() {
isValidated = false;
});
return null;
} else {
setState(() {
isValidated = true;
});
return input;
}
},
decoration: InputDecoration(
labelText: 'Enter your email'),
),
])),
ButtonTheme(
minWidth: 250.0,
child: RaisedButton(
onPressed:
isValidated ? () => print('Signed In') : null,
child: Text("Next"),
),
),
]))))
]));
}
}

How to add validation on the form in flutter

I did manage to get no error for the code but cannot validate the form and show the error message. I have 3 component dart code which is the password, input field, and button. There is also one body dart in the library. ..................
I did manage to get no error for the code but cannot validate the form and show the error message. I have 3 component dart code which is the password, input field, and button. There is also one body dart in the library. ..................
import 'package:flutter_auth/Screens/Login/components/background.dart';
import 'package:flutter_auth/Screens/Login/components/uploadpage.dart';
import 'package:flutter_auth/components/rounded_button.dart';
import 'package:flutter_auth/components/rounded_input_field.dart';
import 'package:flutter_auth/components/rounded_password_field.dart';
class Body extends StatelessWidget {
const Body({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Background(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"LOGIN",
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(height: size.height * 0.03),
RoundedInputField(
hintText: "Username",
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value.length == 0)
return "Please enter email";
else if (!value.contains("#"))
return "Please enter valid email";
else
return null;
},
onChanged: (value) {},
),
PasswordField(
onSaved: (value) {},
),
RoundedButton(
text: "LOGIN",
press: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
},
),
],
),
),
);
}
}
class SecondScreen extends StatelessWidget {
goBackToPreviousScreen(BuildContext context) {
Navigator.pop(context);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Home Page"),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.upload_file,
color: Colors.white,
),
onPressed: () {
{
Navigator.push(
context,
MaterialPageRoute(builder: (context) => uploadpage()),
);
} // do something
},
)
],
),
body: Stack(fit: StackFit.expand, children: <Widget>[
Positioned(
bottom: 0,
width: MediaQuery.of(context).size.width,
child: Center(
child: RaisedButton(
color: Colors.purple[400],
textColor: Colors.white,
onPressed: () {
goBackToPreviousScreen(context);
},
child: Text('Logout')),
),
)
]));
}
Here's a basic example of how Forms work:
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
GlobalKey<FormState> formKey = new GlobalKey();
String formFieldValue;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Form(
key: formKey,
child: Column(
children: [
TextFormField(
validator: (input) {
if (input.isEmpty) {
return 'Please type something';
}
return null;
},
onSaved: (input) => formFieldValue = input,
),
RaisedButton(
onPressed: submitForm,
child: Text(
'Submit'
),
)
],
),
)
);
}
submitForm() {
final formState = formKey.currentState;
if (formState.validate()) {
formState.save();
// then do something
}
}
}
Here the validator does not get called automatically. You have to call it manually onPressed of a button or something.
Here you need to wrap your column in Form widget and give it a key. Onpressed you need to validate it by calling key.currentState.validate()
final _formreg = GlobalKey<FormState>();
Form(key:_formreg, child:Column(children:
[RoundedInputField() ]
));
RaisedButton(onPressed:()=> {
a=_formreg.currentState.validate();
} )
a is a boolean value

Listview scrolling and selecting Textfield afterwards is freezing my app

I am using the package
country_code_picker: ^1.4.0
https://pub.dev/packages/country_code_picker#-installing-tab-
with flutter 1.17.3
Which is pretty much one of the only country code picker packages. But I have one serious problem an I don't have a clue what it could be.
When I run this code
import 'package:flutter/material.dart';
import 'package:country_code_picker/country_code_picker.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
App();
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: TestWidget(),
);
}
}
class TestWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(body: _buildCountryPicker(context));
}
Widget _buildCountryPicker(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Center(
child: CountryCodePicker(
initialSelection: 'NL',
),
),
);
}
}
And I open the dialog to select a country. I scroll in the list and then select the TextField my keyboard opens and when I try to type something my entire app freezes. I can't even hot reload. I don't get a single error.
I am running this on my Huawei P30, but I also experience this on other android devices. I don't know if this is a flutter bug or a country code picker bug.
I think it is probably in this widget somewhere. If anyone could point me in the right direction it would help me alot!
class SelectionDialog extends StatefulWidget {
final List<CountryCode> elements;
final bool showCountryOnly;
final InputDecoration searchDecoration;
final TextStyle searchStyle;
final TextStyle textStyle;
final WidgetBuilder emptySearchBuilder;
final bool showFlag;
final double flagWidth;
final Size size;
final bool hideSearch;
/// elements passed as favorite
final List<CountryCode> favoriteElements;
SelectionDialog(
this.elements,
this.favoriteElements, {
Key key,
this.showCountryOnly,
this.emptySearchBuilder,
InputDecoration searchDecoration = const InputDecoration(),
this.searchStyle,
this.textStyle,
this.showFlag,
this.flagWidth = 32,
this.size,
this.hideSearch = false,
}) : assert(searchDecoration != null, 'searchDecoration must not be null!'),
this.searchDecoration =
searchDecoration.copyWith(prefixIcon: Icon(Icons.search)),
super(key: key);
#override
State<StatefulWidget> createState() => _SelectionDialogState();
}
class _SelectionDialogState extends State<SelectionDialog> {
/// this is useful for filtering purpose
List<CountryCode> filteredElements;
#override
Widget build(BuildContext context) => SimpleDialog(
titlePadding: const EdgeInsets.all(0),
title: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
IconButton(
padding: const EdgeInsets.all(0),
iconSize: 20,
icon: Icon(
Icons.close,
),
onPressed: () => Navigator.pop(context),
),
if (!widget.hideSearch)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextField(
style: widget.searchStyle,
decoration: widget.searchDecoration,
onChanged: _filterElements,
),
),
],
),
children: [
Container(
width: widget.size?.width ?? MediaQuery.of(context).size.width,
height:
widget.size?.height ?? MediaQuery.of(context).size.height * 0.7,
child: ListView(
children: [
widget.favoriteElements.isEmpty
? const DecoratedBox(decoration: BoxDecoration())
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...widget.favoriteElements.map(
(f) => SimpleDialogOption(
child: _buildOption(f),
onPressed: () {
_selectItem(f);
},
),
),
const Divider(),
],
),
if (filteredElements.isEmpty)
_buildEmptySearchWidget(context)
else
...filteredElements.map(
(e) => SimpleDialogOption(
key: Key(e.toLongString()),
child: _buildOption(e),
onPressed: () {
_selectItem(e);
},
),
),
],
),
),
],
);
Widget _buildOption(CountryCode e) {
return Container(
width: 400,
child: Flex(
direction: Axis.horizontal,
children: <Widget>[
if (widget.showFlag)
Flexible(
child: Padding(
padding: const EdgeInsets.only(right: 16.0),
child: Image.asset(
e.flagUri,
package: 'country_code_picker',
width: widget.flagWidth,
),
),
),
Expanded(
flex: 4,
child: Text(
widget.showCountryOnly
? e.toCountryStringOnly()
: e.toLongString(),
overflow: TextOverflow.fade,
style: widget.textStyle,
),
),
],
),
);
}
Widget _buildEmptySearchWidget(BuildContext context) {
if (widget.emptySearchBuilder != null) {
return widget.emptySearchBuilder(context);
}
return Center(
child: Text('No country found'),
);
}
#override
void initState() {
filteredElements = widget.elements;
super.initState();
}
void _filterElements(String s) {
s = s.toUpperCase();
setState(() {
filteredElements = widget.elements
.where((e) =>
e.code.contains(s) ||
e.dialCode.contains(s) ||
e.name.toUpperCase().contains(s))
.toList();
});
}
void _selectItem(CountryCode e) {
Navigator.pop(context, e);
}
}
Also filed an issue on the flutter github https://github.com/flutter/flutter/issues/59886
Edit:
I have a video of it right here
https://www.youtube.com/watch?v=669KitFG9ek&feature=youtu.be
I just had to remove the keys, so there probably was a duplicate key
...filteredElements.map(
(e) => SimpleDialogOption(
//key: Key(e.toLongString()),
child: _buildOption(e),
onPressed: () {
_selectItem(e);
},
),
),