Related
I'm stuck on a small point, I'm developing a self-help service application and I take care of creating the form to create an announcement.
For that I thought it a great idea to set it up as a Cupertino Stepper, but when I want the user to choose an image from a list I give, I don't know how to make an image selectable. Here is a picture of what I have so far (left) and what I would like (right):
Comparison between what I have and what I want
And here is the code of the page I have:
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
Stepper(
currentStep: currentStep,
onStepTapped: (index) {
setState(() => currentStep = index);
},
onStepContinue: () {
if (currentStep != 3) {
setState (() => currentStep++);
}
},
onStepCancel: () {
if (currentStep != 0) {
setState (() => currentStep--);
}
},
steps: [
Step(
isActive: currentStep >= 0,
title: Text('Choisissez une catégorie'),
content: CupertinoPageScaffold(
child: DefaultTextStyle(
style: TextStyle(
color: CupertinoColors.label.resolveFrom(context),
fontSize: 22.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Catégorie séléctionnée : ', style: TextStyle(fontSize: 14),),
CupertinoButton(
padding: EdgeInsets.zero,
// Display a CupertinoPicker with list of fruits.
onPressed: () => _showDialog(
CupertinoPicker(
magnification: 1.22,
squeeze: 1.2,
useMagnifier: true,
itemExtent: _kItemExtent,
onSelectedItemChanged: (int selectedItem) {
setState(() {
_selectedCategorie = selectedItem;
});
},
children:
List<Widget>.generate(_CategorieNames.length, (int index) {
return Center(
child: Text(
_CategorieNames[index],
),
);
}),
),
),
// This displays the selected fruit name.
child: Text(
_CategorieNames[_selectedCategorie],
),
),
],
),
),
)
),
Step(
isActive: currentStep >= 1,
title: Text("Choisir le titre de l'annonce"),
content: Padding(
padding: EdgeInsets.only(top: 20),
child: TextField(
maxLength: 20,
decoration: InputDecoration(
border: OutlineInputBorder(borderRadius: BorderRadius.circular(30)),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 1.5),
borderRadius: BorderRadius.circular(30)
),
labelText: "Titre de l'annonce"
),
),
)
),
Step(
isActive: currentStep >= 2,
title: Text('Ajouter une description'),
content: Padding(
padding: EdgeInsets.only(top: 20),
child: TextField(
keyboardType: TextInputType.multiline,
maxLines: null,
maxLength: 250,
decoration: InputDecoration(
border: OutlineInputBorder(borderRadius: BorderRadius.circular(30)),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 1.5),
borderRadius: BorderRadius.circular(30)
),
labelText: "Description de l'annonce"
),
),
)
),
Step(
isActive: currentStep >= 3,
title: Text('Ajouter une image'),
content: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child:
Image.asset("images/Jardinage.png"),
),
Expanded(
child:
Image.asset("images/baby sitting.png"),
),
Expanded(
child:
Image.asset("images/Coiffure.png"),
),
],
),
),
],
)
],
),
),
);
I thank you in advance for your help !
You can make the image selectable by adding GestureDetector and changing the _selectedImageIndex using setState on each tap.
Step(
isActive: currentStep >= 3,
title: const Text('Ajouter une image'),
content: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
_selectedImage = 0;
});
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: _selectedImage == 0
? Colors.green
: Colors.transparent)),
child: Image.asset(
"assets/images/provinces/1.png"))),
),
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
_selectedImage = 1;
});
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: _selectedImage == 1
? Colors.green
: Colors.transparent)),
child: Image.asset(
"assets/images/provinces/2.png"))),
),
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
_selectedImage = 2;
});
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: _selectedImage == 2
? Colors.green
: Colors.transparent)),
child: Image.asset(
"assets/images/provinces/3.png"))),
),
],
),
),
Alternate Solution : You can refactor the image selector widget as well
The variables will be
var _selectedImageIndex = 0;
final _images = [
"assets/images/provinces/1.png",
"assets/images/provinces/2.png",
"assets/images/provinces/3.png",
];
SelectabImage widget will be
class SelectableImage extends StatelessWidget {
const SelectableImage({
Key? key,
required this.isSelected,
required this.imageAsset,
required this.onTap,
}) : super(key: key);
final bool isSelected;
final String imageAsset;
final void Function(String imageAsset) onTap;
#override
Widget build(BuildContext context) {
return Expanded(
child: GestureDetector(
onTap: () => onTap(imageAsset),
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: isSelected ? Colors.green : Colors.transparent)),
child: Image.asset(imageAsset),
),
),
);
}
}
Step function will be reduced to
Step(
isActive: currentStep >= 3,
title: const Text('Ajouter une image'),
content: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (int i = 0; i < _images.length; i++)
SelectableImage(
isSelected: _selectedImageIndex == i,
onTap: (selectedImageIndex) {
setState(() {
_selectedImageIndex = i;
});
},
imageAsset: _images[i],
),
],
),
),
So I'm trying to update the value of the drop down list using the setState, but when I select a value from the list, the value on the screen won't be able to change
import 'package:demo_app_admin/Custom/custom_Font.dart';
import 'package:flutter/material.dart';
import '/Custom/Custom_Raised_Bottun.dart';
import '/Custom/Header.dart';
import '/Custom/inputField.dart';
class LoginView extends StatefulWidget {
#override
_LoginViewState createState() => _LoginViewState();
}
class _LoginViewState extends State<LoginView> {
#override
Widget build(BuildContext context) {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final isKeyboard = MediaQuery.of(context).viewInsets.bottom != 0;
String _dropdownvalue = "Global admin";
List<String> _items = <String> ["Global admin", "Institution admin"];
return Scaffold(
body: Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: LinearGradient(begin: Alignment.topCenter, colors: [
Colors.teal[700]!,
Colors.teal[200]!,
Colors.teal[400]!
]),
),
child: Column(
children: <Widget>[
const SizedBox(
height: 80,
),
if (!isKeyboard)
Header(
padding: const EdgeInsets.all(20),
crossAxisAlignment: CrossAxisAlignment.start,
head: "Welcome",
headTextStyle:
const TextStyle(color: Colors.white, fontSize: 40),
sizedBoxHeight: 10,
subtitle: "Sign In to Your Admin Account",
subtitleTextStyle:
const TextStyle(color: Colors.white, fontSize: 18),
),
Expanded(
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(60),
topRight: Radius.circular(60),
)),
child: Padding(
padding: const EdgeInsets.all(30),
child: SingleChildScrollView(
reverse: true,
padding: EdgeInsets.all(32),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
const SizedBox(
height: 40,
),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10)),
child: Column(
children: <Widget>[
InputField(
labelText: 'Email',
padding: EdgeInsets.all(10),
borderSide: BorderSide(color: Colors.grey),
hintText: "Enter your email",
color: Colors.grey,
inputBorder: InputBorder.none,
obscureText: false,
enableSuggestion: true,
autoCorrect: true,
onSaved: (value) {},
// (value){controller.email = value!;},
validator: (value) {
if (value == null) {
print("ERROR");
}
},
),
InputField(
labelText: 'Password',
padding: EdgeInsets.all(10),
borderSide: BorderSide(color: Colors.grey),
hintText: "Enter your password",
color: Colors.grey,
inputBorder: InputBorder.none,
obscureText: true,
enableSuggestion: false,
autoCorrect: false,
onSaved: (value) {},
// (value){ controller.password = value!;},
validator: (value) {
if (value == null) {
print("ERROR");
}
},
),
],
),
),
const SizedBox(
height: 40,
),
here is the issue
DropdownButton<String>(
value: _dropdownvalue,
icon: Icon(Icons.keyboard_arrow_down),
items: _items.map((String _items) {
return DropdownMenuItem<String>(
value: _items,
child: CustomFont(text: _items),
);
}).toList(),
onChanged: (value) {
setState(() => _dropdownvalue = value!);
}),
const SizedBox(
height: 40,
),
CustomRaisedButton(
width: 200,
height: 50.0,
margin: const EdgeInsets.symmetric(horizontal: 50),
color: Colors.teal.shade500,
borderRadius: BorderRadius.circular(10),
text: "LOGIN",
textColor: Colors.white,
fontSize: 17,
fontWeight: FontWeight.bold,
function: () {}
// {
// _formKey.currentState?.save();
// if(_formKey.currentState?.validate() !=null){
// controller.signInWithEmailAndPassword();
// }
// },
),
SizedBox(
height: 10,
),
],
),
),
),
),
))
],
),
),
);
}
}
The issue is here, you are declaring variables inside build. Therefore, variables get reset to default value on every build. Means setState.
Declare variables outside the build method.
class _LoginViewState extends State<LoginView> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _dropdownvalue = "Global admin";
List<String> _items = <String>["Global admin", "Institution admin"];
#override
Widget build(BuildContext context) {
final isKeyboard = MediaQuery.of(context).viewInsets.bottom != 0;
return Scaffold(
More about StatefulWidget.
I want the button to be inactive until 10 characters are entered in the field. When 10 characters were entered, the button was active. And when it is inactive it is gray, and when it is active it is blue. How can I do that?
Here is the input code with the button:
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Padding(
padding: EdgeInsets.fromLTRB(
20, MediaQuery.of(context).size.height * 0, 20, 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
onChanged: (String value) {
setState(() {
_showIcon = value.isNotEmpty;
});
},
controller: _inputController,
decoration: InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 2.0),
),
hintText: "(1201) 565-0123 ",
hintStyle: TextStyle(color: Colors.grey, fontSize: 15),
helperText: 'Enter your phone number',
helperStyle: TextStyle(color: Colors.grey, fontSize: 15),
suffixIcon: _showIcon
? IconButton(
onPressed: () {
setState(() {
_inputController.clear();
_showIcon = false;
});
},
icon: const Icon(Icons.close, color: Colors.grey),
) : null,
),
keyboardType: TextInputType.number,
inputFormatters: [maskFormatter],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: () {
},
child: const Icon(Icons.arrow_forward_rounded, size: 25),
style: ElevatedButton.styleFrom(
shape: CircleBorder(),
padding: EdgeInsets.all(15)
)
),
],
)
],
),
),
),
);
}
}
You can call setState(() {}); on onChanged to update the UI, or add listener on _inputController.
ElevatedButton(
onPressed:
_inputController.text.length < 10 ? null : () {},
...
Passing onPressed:null will provide disable state.
Updating UI can be done
TextField(
onChanged: (String value) {
setState(() {});
},
....)
Or
late final TextEditingController _inputController;
#override
void initState() {
super.initState();
_inputController = TextEditingController()
..addListener(() {
setState(() {});
});
}
Use a variable like isEnabled and passing null to the onPress function will disable the button.
bool isEnabled=false;
void callbackfunction(){
// add your logic here.
}
....
....
TextField(
onChanged: (String value) {
if (value.length == 10){
setState(()=> isEnabled = true;)
}
else{
isEnabled=false;
}
setState(() {
_showIcon = value.isNotEmpty;
});
},
....
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: isEnabled ? callbackfunction : null,
child: const Icon(Icons.arrow_forward_rounded, size: 25),
style: ElevatedButton.styleFrom(
color: isEnabled ? Colors.blue : Colors.grey,
shape: CircleBorder(),
padding: EdgeInsets.all(15)
)
),
],
)
],
),
P.S Please check the syntax I have just provided you the concept.
This my contacts list page
class Contacts extends StatefulWidget with NavigationStates {
#override
_ContactsState createState() => _ContactsState();
}
class _ContactsState extends State<Contacts>{
DatabaseHelper databaseHelper = DatabaseHelper();
List<contacts> contactsList;
int count = 0;
#override
Widget build(BuildContext context, ) {
if(contactsList == 0){
contactsList = List<contacts>();
updateListView();
}
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text("Contacts"),
backgroundColor: Colors.lightGreenAccent,
centerTitle: true,
),
body: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(4.0),
margin: EdgeInsets.all(5.0),
child: TextField(
//controller: searchController,
decoration: InputDecoration(
labelText:'Search Contacts',
border: new OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(25)),
borderSide: new BorderSide(
color: Colors.pinkAccent
)
),
prefixIcon: Icon(
Icons.search,
color: Colors.black,
)
),
),
),
Expanded(
child: ListView.builder(
itemCount: count,
itemBuilder: (context , int position){
return Card(
elevation: 1.0,
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.pinkAccent,width: 1),
borderRadius: BorderRadius.circular(20)
),
child: Container(
margin: EdgeInsets.all(6.0),
padding: EdgeInsets.all(4.0),
color: Colors.white,
child: ListTile(
leading: CircleAvatar(
radius: 30.0,
backgroundColor: Colors.lightBlueAccent,
child: Icon(Icons.person,color: Colors.black,),
),
title: Text(this.contactsList[position].first_name,style: TextStyle(color: Colors.black,fontSize: 28.0),),
subtitle: Text(this.contactsList[position].last_name,style:TextStyle(color: Colors.black38,fontSize: 15.0),),
trailing: GestureDetector(
child: Icon(Icons.delete, color: Colors.pinkAccent,),
onTap: () {
_delete(context, contactsList[position]);
},
),
),
),
);
},
),
)
],
),
floatingActionButton: new FloatingActionButton(onPressed: null,
child: new Icon(Icons.dialpad,color: Colors.black,size: 30,),
backgroundColor: Colors.pinkAccent,
),
bottomNavigationBar: CurvedNavigationBar(
color: Colors.lightGreenAccent,
backgroundColor: Colors.white,
buttonBackgroundColor: Colors.pinkAccent,
height: 50,
index: 1,
items:<Widget>[
Icon(Icons.call,size: 25,color: Colors.black,),
Icon(Icons.home,size: 30,color: Colors.black,),
Icon(Icons.person_add_rounded,size: 25,color: Colors.black,),
],
animationDuration: Duration(
milliseconds: 400
),
animationCurve: Curves.easeIn,
onTap: (index) async {
if (index == 0)
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return logs();
}
)
);
if (index == 1)
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return Contacts();
}
)
);
if (index == 2)
navigateToDetail(contacts('',''));
}
),
);
}
updateListView() {
final Future<Database> dbFuture = databaseHelper.initalizeDatabase();
dbFuture.then((database) {
Future<List<contacts>> contactsListFuture = databaseHelper.getContactList();
contactsListFuture.then((contactsList){
setState(() {
this.contactsList = contactsList;
this.count = contactsList.length;
});
});
});
}
Color getStorageColor() {
int storage;
switch (storage) {
case 1:
return Colors.pinkAccent;
break;
case 2:
return Colors.lightBlueAccent;
break;
default:
return Colors.lightBlueAccent;
}
}
void navigateToDetail(contacts contact) async{
bool result = await Navigator.push(context, MaterialPageRoute(builder: (context) {
return AddContacts(contact);
}));
if (result == true) {
updateListView();
}
}
void _delete(BuildContext context, contacts contact) async {
int result = await databaseHelper.deleteContact(contact.id);
if (result != 0) {
_SnackBar(context, 'Contact Deleted Successfully');
updateListView();
}
}
void _SnackBar(BuildContext context, String message) {
final snackBar = SnackBar(
content: Text(message),
action: SnackBarAction(
label: 'Undo',
onPressed: (){},
),
);
// ignore: deprecated_member_use
Scaffold.of(context).showSnackBar(snackBar);
}
}
This is my contacts details page
import 'dart:io';
//import 'package:contacts_service/contacts_service.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
//import 'package:sqflite/sqflite.dart';
import 'package:mycontacts_app/models/Contact.dart';
import 'dart:async';
import 'package:mycontacts_app/utils/database_helper.dart';
//import 'package:intl/intl.dart';
class AddContacts extends StatefulWidget {
final contacts contact;
AddContacts(this.contact);
//AddContacts(contacts contact);
#override
State<StatefulWidget> createState() {
// _AddContactsState();
return _AddContactsState(this.contact);
}
}
class _AddContactsState extends State<AddContacts> {
//TextEditingController _fnameController,_numberController,_lnameController;
DatabaseHelper helper = DatabaseHelper();
PickedFile _imageFile;
final ImagePicker _picker = ImagePicker();
_AddContactsState(this.contact);
TextEditingController _fnameController = TextEditingController();
TextEditingController _numberController = TextEditingController();
TextEditingController _lnameController = TextEditingController();
contacts contact;
List _Storage = ['Phone','Sim'];
//String _storageval;
#override
Widget build(BuildContext context) {
//_nameController = contacts.first_name
_fnameController.text = contact.first_name;
_lnameController.text = contact.last_name;
_numberController.text = contact.phone_no as String;
return Scaffold(
appBar: AppBar(
title: Text("New Contact"),
backgroundColor: Colors.lightGreenAccent,
centerTitle: true,
),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(
vertical: 40.0,
horizontal: 10.0,
),
//margin: EdgeInsets.all(15),
child: Form(
child: Column(
//crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
padding: EdgeInsets.only(left: 16.0,right: 16.0),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white
),
borderRadius: BorderRadius.circular(20.0),
),
child: DropdownButton(
hint: Text('Store In '),
dropdownColor: Colors.black12,
elevation: 5,
icon: Icon(Icons.arrow_drop_down),
iconSize: 20.0,
isExpanded: true,
style: TextStyle(
color: Colors.black,fontSize: 18.0
),
items: _Storage.map((value){
return DropdownMenuItem(
value: value,
child: Text(value),
);
}).toList(),
value: getStorageAsString(contact.storage),
onChanged: (value){
setState(() {
//_storageval = value;
updateStorageAsInt(value);
});
},
),
),
),
imageProfile(),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _fnameController,
onChanged: (value){
updateFirstname();
},
decoration: InputDecoration(
hintText: 'First Name',
prefixIcon: Icon(Icons.person),
//prefixText: "Name",
suffixIcon: Icon(Icons.keyboard_arrow_down),
fillColor: Colors.white,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
contentPadding: EdgeInsets.all(15),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _lnameController,
onChanged: (value){
updateLastName();
},
decoration: InputDecoration(
hintText: 'Last Name',
prefixIcon: Icon(Icons.person),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
fillColor: Colors.white,
filled: true,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
contentPadding: EdgeInsets.all(15),
),
),
),
// SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _numberController,
onChanged: (value){
//updateNumber();
},
decoration: InputDecoration(
hintText: 'Number',
prefixIcon: Icon(Icons.phone_android),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
//SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
//controller: _nameController,
decoration: InputDecoration(
hintText: 'Address',
prefixIcon: Icon(Icons.location_on_rounded),
//prefixText: "Name",
suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
//SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
//controller: _nameController,
decoration: InputDecoration(
hintText: 'Email',
prefixIcon: Icon(Icons.email),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
//SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
//controller: _nameController,
decoration: InputDecoration(
hintText: 'Website',
prefixIcon: Icon(Icons.language),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
//SizedBox(height: 15),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
//controller: _nameController,
decoration: InputDecoration(
hintText: 'Work Info',
prefixIcon: Icon(Icons.business),
//prefixText: "Name",
//suffixIcon: Icon(Icons.keyboard_arrow_down),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
),
fillColor: Colors.white,
filled: true,
contentPadding: EdgeInsets.all(15),
),
),
),
/*ListView.builder(
itemBuilder: (context, index){
return ExpansionTile(
title: ListTile(
title: TextField(
decoration: InputDecoration(
hintText: "Name"
),
style: TextStyle(
color: Colors.black,
fontSize: 15.0,
),
),
),
children: <Widget>[
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: "Name Prefix"
),
)
),
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: " First Name"
),
)
),
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: " Middle Name"
),
)
),
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: "Last Name"
),
)
),
ListTile(
title:TextFormField(
decoration: InputDecoration(
hintText: "Name Suffix"
),
)
)
],
);
}
)*/
Padding(
padding: const EdgeInsets.only(top: 15.0, bottom: 15.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
color: Colors.lightGreenAccent,
textColor: Colors.black,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.pinkAccent),
),
onPressed: () {
debugPrint("Save button clicked");
_save();
},
child: Text(
"Save"
),
),
),
Container(width: 5.0,),
Expanded(
child: RaisedButton(
color: Colors.lightGreenAccent,
textColor: Colors.black,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.pinkAccent),
),
onPressed: () {
_delete();
},
child: Text(
"Cancel"
),
),
)
],
),
)
],
),
),
),
),
);
}
Widget imageProfile() {
return Center(
child: Stack(
children: <Widget>[
CircleAvatar(
radius: 50.0,
backgroundImage: _imageFile==null? AssetImage("assets/default.png"):FileImage(File(_imageFile.path)),
),
Positioned(
bottom: 20.0,
right: 20.0,
child: InkWell(
onTap: () {
showModalBottomSheet(
context: context,
builder: ((builder) => bottomSheet()),
);
},
child: Icon(
Icons.camera_alt,
color: Colors.lightGreenAccent,
size: 28.0,
),
),
),
],
),
);
}
Widget bottomSheet() {
return Container(
height: 100.0,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(
horizontal: 20,
vertical: 20,
),
child: Column(
children: <Widget>[
Text(
"Choose Contact Image",
style: TextStyle(
fontSize: 20,
),
),
SizedBox(
height: 20,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.camera),
onPressed: (){
takePhoto(ImageSource.camera);
},
label: Text("Camera"),
),
FlatButton.icon(
icon: Icon(Icons.image),
onPressed: (){
takePhoto(ImageSource.gallery);
},
label: Text("Gallery"),
)
],
)
],
),
);
}
void takePhoto(ImageSource source) async {
final pickedFile = await _picker.getImage(
source: source,
);
setState(() {
_imageFile = pickedFile;
});
}
void updateFirstname(){
contact.first_name = _fnameController.text;
}
// Update the description of Note object
void updateLastName() {
contact.last_name = _lnameController.text;
}
/*void updateNumber() {
contact.phone_no = _numberController.text as int;
}*/
void _save() async {
moveToLastScreen();
//n.date = DateFormat.yMMMd().format(DateTime.now());
int result;
if (contact.id != null) { // Case 1: Update operation
result = await helper.updateContact(contact);
} else { // Case 2: Insert Operation
result = await helper.insertContact(contact);
}
if (result != 0) { // Success
_showAlertDialog('Status', 'Contact Saved Successfully');
} else { // Failure
_showAlertDialog('Status', 'Problem Saving Contact');
}
}
void moveToLastScreen() {
//Navigator.pop(context);
Navigator.pop(context, true);
}
void _delete() async {
moveToLastScreen();
// Case 1: If user is trying to delete the NEW NOTE i.e. he has come to
// the detail page by pressing the FAB of NoteList page.
if (contact.id == null) {
_showAlertDialog('Status','No Contact was deleted');
return;
}
// Case 2: User is trying to delete the old note that already has a valid ID.
int result = await helper.deleteContact(contact.id);
if (result != 0) {
_showAlertDialog('Status','Contact Deleted Successfully');
} else {
_showAlertDialog('Status', 'Error Occured while Deleting Contact');
}
}
void _showAlertDialog(String title, String message) {
AlertDialog alertDialog = AlertDialog(
title: Text(title),
content: Text(message),
);
showDialog(
context: context,
builder: (_) => alertDialog
);
}
void updateStorageAsInt(String value) {
switch (value) {
case 'Phone':
contact.storage = 1;
break;
case 'Sim':
contact.storage = 2;
break;
}
}
// Convert int priority to String priority and display it to user in DropDown
String getStorageAsString(int value) {
String storage;
switch (value) {
case 1:
storage = _Storage[0]; // 'High'
break;
case 2:
storage = _Storage[1]; // 'Low'
break;
}
return storage;
}
}
The contact card and icon is displayed but the name is not displaying.
I was even getting error like :-
This widget has been unmounted, so the State no longer has a context (and should be considered defunct).
It is not even showing the position or file of error
And I am not being able to solve the error .
I have designed a ui using flutter first I checked it in my phone which is Moto g5s plus the ui looks goods and I occupies entire screen but when I open the same app in iPhone 11 pro max I am getting a huge empty space but when I open it in iPhone 8 then the ui looks fine as it is in Moto g5s plus. I want to know how to have same consistent ui across different device sizes in flutter?
class Login extends StatefulWidget
{
#override
State<StatefulWidget> createState() {
return LoginState();
}
}
class LoginState extends State<Login>
{
String _email,_password;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState()
{
super.initState();
}
Widget _progressBar(AuthProvider authProvider)
{
//print("progress"+authProvider.progressStatus.toString());
return Visibility(
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: authProvider.progressStatus,
child: Container(
child: Center(
child: SizedBox(
width: 60,
height: 60,
child: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 1.0,
),
],
),
),
Center(
child: CircularProgressIndicator(),
)
],
),
)
)
),
);
}
Widget _emailTextField(AuthProvider authProvider)
{
return TextFormField(
onChanged: (String value){
authProvider.checkEmail(value);
},
decoration: InputDecoration(
labelText: "Email id",
errorText: authProvider.emailStatus ? null : "Enter a valid email",
border: OutlineInputBorder(
borderRadius: new BorderRadius.circular(32.0),
)
),
keyboardType: TextInputType.emailAddress,
validator: (String value){
if(value.isEmpty || !RegExp(r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?").hasMatch(value))
{
return "Enter a valid email";
} else {
return null;
}
},
onSaved: (String value){
_email = value;
},
);
}
Widget _passwordTextField(AuthProvider authProvider)
{
//print("pass check "+authProvider.passStatus.toString());
return TextFormField(
decoration: InputDecoration(labelText: "Password",
filled: true,
errorText: authProvider.passStatus ? null : "Password is too short",
border: OutlineInputBorder(
borderRadius: new BorderRadius.circular(32.0),
),
fillColor: Colors.white
),
keyboardType: TextInputType.text,
obscureText: true,
onChanged: (String value){
authProvider.checkPassword(value);
},
validator: (String value){
if(value.isEmpty)
{
return "Enter a valid password";
}
else if(value.length < 8)
{
return "Password is too short";
}
else
{
return null;
}
},
onSaved: (String value){
_password = value;
},
);
}
void _login(AuthProvider authProvider)
{
if(!_formKey.currentState.validate())
{
return;
}
_formKey.currentState.save();
Map<String,String> map = new Map();
map['email'] = _email;
map['password'] = _password;
authProvider.login(map);
}
#override
Widget build(BuildContext context) {
final authProvider = Provider.of<AuthProvider>(context);
if(authProvider.loginStatus != null && authProvider.loginStatus != "success")
{
_scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text('${authProvider.loginStatus}',
style: TextStyle(color: Colors.black),),
backgroundColor: Color(0xFFe5e5e5),
));
}
return Scaffold(
key: _scaffoldKey,
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
alignment: Alignment.center,
margin: EdgeInsets.fromLTRB(0, 48, 0, 0),
child: Text(
"Take Orders",
style: TextStyle(color: Theme.of(context).primaryColorDark,fontSize: 20),
),
),
Container(
child: Text(
"Track the Best Selling Items",
style: TextStyle(color: Theme.of(context).primaryColor,fontSize: 16),
),
),
Container(
margin: EdgeInsets.fromLTRB(16, 0, 16, 0),
child: SvgPicture.asset('assets/images/undraw_booking.svg',width: 100.0,height: 280.0,),
),
Container(
margin: EdgeInsets.fromLTRB(16, 0, 0, 0),
child:Row(
children: <Widget>[
Text(
"Login To ",
style: TextStyle(color: Colors.black,fontSize: 20)
),
Text(
"Take orders",
style: TextStyle(color: Theme.of(context).primaryColorDark,fontSize: 20),
)
],
),
),
Container(
margin: EdgeInsets.fromLTRB(16, 8, 16, 0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
//_emailTextField(_loginBloc),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: _emailTextField(authProvider),
),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: _passwordTextField(authProvider),
),
Container(
margin: EdgeInsets.fromLTRB(0, 8, 0, 0),
child: Align(
alignment: Alignment.centerLeft,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(32.0)
),
padding: EdgeInsets.fromLTRB(64, 12, 64, 12),
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text(
"Login",
),
onPressed: (){
_login(authProvider);
},
) ,
),
),
],
),
),
),
],
),
)
),
_progressBar(authProvider),
],
),
);
}
}
images of emulator
without seeing code i cannot advise you proper solution however, i guess that tricks will solve your many issues.
instead of using fixed values
try to use
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
you can also use them like
height: MediaQuery.of(context).size.height * 0.80, // 80% of screen height
width: MediaQuery.of(context).size.width * 0.35, // 35% of screen width
Hope will help you