value of the title and description repeats every time a new todo is made - flutter

I just started learning flutter and am trying to create a todo app, but every time a new todo is made the value of the title and the description remains the same for all the todos,
I have tried every method but no difference pls tell me what's wrong with the code and how do I save the value of the title and description for each todo?
My code:
class _HomePageState extends State<HomePage> {
TextEditingController _titleController = TextEditingController();
TextEditingController _detailController = TextEditingController();
List todos = [];
#override
void initState() {
super.initState();
todos.add('');
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
),
color: const Color(0xfff6f6f6f6),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(bottom: 32.0, top: 32.0),
child: const Text(
"Reminders",
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold
),
),
),
Expanded(
child: ListView.builder(
itemCount: todos.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: Key(todos[index]),
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 24.0
),
margin: const EdgeInsets.only(
bottom: 20.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
cursorColor: Colors.black,
autofocus: true,
controller: _titleController,
style: const TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold
),
decoration: const InputDecoration(
hintText: "Enter a title",
border: InputBorder.none,
),
),
const Divider(
color: Colors.black,
),
Padding(
padding: const EdgeInsets.only(top: 0.0),
child: TextField(
controller: _detailController,
style: TextStyle(
fontSize: 20.0,
color: Colors.grey[900],
),
cursorColor: Colors.black,
maxLines: null,
decoration: const InputDecoration(
hintText: "Enter the description",
label: Text("description"),
border: InputBorder.none
),
),
),
],
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.0)
),
),
);
},
),
)
],
),
Positioned(
bottom: 24.0,
right: 0.0,
child: GestureDetector(
onTap: () {
setState(() {
todos.add('');
});
},
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.circular(20.0),
),
child: const Icon(Icons.add, color: Colors.white, size: 35.0),
),
),
)
],
),
),
),
);
}
}

Hello and welcome to the world of flutter,
like you do for title and detail, every textfield needs it's own TextEditingController. So you could add a list of controllers for title and description.
List<TextEditingController> _titleController = [];
List<TextEditingController> _detailController = [];
and add an entry to both, when you add todo.
todo.add('')
_titleController.add(TextEditingController())
_detailController.add(TextEditingController())
At the TextFields you should reference by index:
...
child: TextField(controller: _detailController[index],
...
This should help with your problem.
I would recommend you to look at some tutorials and try to rebuild them.
Have fun!

Related

Flutter: Navigator Push changes position of my Background Image

Two Files:
account_page.dart
& cart_page.dart
I used Navigator.push to embed AccountPage() [from account_page.dart] within CartPage() (inside cart_page.dart). When I check the simulation, the background image widget within the Stack() changes position.
How can I make the NavigationPage identical to the original? Is this a bug?
I've tried many things including wrapping the Container() that holds the image in a Positioned(), SizedBox(), 'alignment: Alignment(x,y)', adding a column that shifts the image down. Most of these end with the picture completely disappearing, I erased parameters to make the image free as possible and then tried again to no avail.
Initially, I used 'alignment: Alignment(0.0, -7.0)' to position the image. However, when the page is called using Navigator, the image alignment changes from a negative to a positive causing the position to move the opposite direction.
The other solutions I've thought of require some photoshop, but I don't want to mess with the image unless I really have to.
I believe it has something to do with the image being in a stack and causing some overflow.
Any suggestions would be helpful.
Code:
account_page.dart
import 'package:email_validator/email_validator.dart';
import 'package:flutter/material.dart';
class AccountPage extends StatefulWidget {
const AccountPage({Key? key}) : super(key: key);
#override
_AccountPageState createState() => _AccountPageState();
}
class _AccountPageState extends State<AccountPage> {
bool _obscureText = true;
bool _passswordVisible = false;
void _toggleObscureText() {
setState(() {
_obscureText = !_obscureText;
_passswordVisible = !_passswordVisible;
});
}
String? get _showHideString {
if (!_passswordVisible) {
return "Show";
} else {
return "Hide";
}
}
#override
Widget build(BuildContext context) {
// create a global key that can provide validation
final _formKey = GlobalKey<FormState>();
return Form(
key: _formKey,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
foregroundColor: Colors.black,
elevation: 0,
),
body: Stack(
children: [
Container(
//*****************AREA OF PROBLEM**************************
width: MediaQuery.of(context).size.width,
decoration: const BoxDecoration(
color: Colors.white,
image: DecorationImage(
image: AssetImage("images/background.jpeg"),
fit: BoxFit.fitWidth,
//---------sets the position of image------------
alignment: Alignment(0.0, -7.0),
),
),
),
SingleChildScrollView(
child: Column(
children: <Widget>[
const Padding(
padding: EdgeInsets.all(30.0),
child: Text(
"Sign in",
style: TextStyle(
fontFamily: "RaleWay",
fontSize: 30,
fontWeight: FontWeight.bold),
),
),
const Padding(
padding: EdgeInsets.only(left: 20, right: 20, bottom: 30),
child: Text(
"Become a member to enjoy exclusive savings on your favorite items.",
style: TextStyle(
fontSize: 16,
),
textAlign: TextAlign.center,
),
),
Stack(
children: <Widget>[
SingleChildScrollView(
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 10),
child: Column(
children: [
TextFormField(
validator: (value) {
if (EmailValidator.validate(value!)) {
return null;
} else {
return "Please enter a valid Username";
}
},
autocorrect: false,
autofocus: false,
style: const TextStyle(fontSize: 18),
decoration: InputDecoration(
hintText: 'UserName',
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[200],
contentPadding: const EdgeInsets.all(10.0),
),
),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 25,
),
child: Stack(children: <Widget>[
TextFormField(
autocorrect: false,
autofocus: false,
obscureText: _obscureText,
style: const TextStyle(fontSize: 18),
decoration: InputDecoration(
hintText: "Password",
filled: true,
fillColor: Colors.grey[200],
contentPadding:
const EdgeInsets.all(10.0),
),
),
Container(
alignment: Alignment.bottomRight,
child: TextButton(
onPressed: () {
_toggleObscureText();
},
child: Text(_showHideString!),
style: ButtonStyle(
overlayColor:
MaterialStateProperty.all(
Colors.transparent)
// MaterialStateProperty
// .resolveWith<Color?>(
// (Set<MaterialState> states) {
// if (states.contains(
// MaterialState.pressed)) {
// return Theme.of(context)
// .colorScheme
// .primary
// .withOpacity(0);
// }
// }),
),
))
]),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
child: const Text(
"Forgot Password?",
style: TextStyle(
decoration: TextDecoration.underline,
),
),
onPressed: () {},
style: ButtonStyle(
overlayColor:
MaterialStateProperty.all<Color>(
Colors.transparent,
)),
),
],
),
RawMaterialButton(
onPressed: () {
// ignore: todo
// TODO: Checks if username and password is in the system, this will bring to real account page
// if not, replies, please enter a valid username and password
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Submitted!"),
),
);
}
},
constraints:
const BoxConstraints(minWidth: 300),
splashColor: Colors.black12,
fillColor: Colors.black,
padding:
const EdgeInsets.symmetric(vertical: 12),
child: const Text(
"Login",
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
],
)
],
),
),
],
),
),
);
}
}
cart_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_mobile_sim_test_1/account_page.dart';
class CartPage extends StatefulWidget {
const CartPage({Key? key}) : super(key: key);
#override
_CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text(
"Your Cart",
style: TextStyle(fontSize: 24, color: Colors.black),
),
elevation: 0,
backgroundColor: Colors.white,
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: MediaQuery.of(context).size.width,
height: 100,
alignment: Alignment.center,
padding: const EdgeInsets.all(10.0),
child: const Text(
"Your Shopping Bag is Empty",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
RawMaterialButton(
child: const Text("Sign In",
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold)),
//*****************NAVIGATOR PUSH**************************
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const AccountPage()),
);
},
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width,
minHeight: 20),
padding: const EdgeInsets.all(12.0),
fillColor: Colors.black,
),
Stack(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: const Divider(
color: Colors.grey,
thickness: 2,
),
),
),
Container(
color: Colors.transparent,
width: (MediaQuery.of(context).size.width),
alignment: Alignment.topCenter,
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.white,
width: 40,
child: const Text(
"or",
style: TextStyle(
fontSize: 18,
color: Colors.grey,
),
textAlign: TextAlign.center,
),
),
),
],
),
RawMaterialButton(
onPressed: () {},
child: const Text("Create Account",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
fillColor: Colors.white,
shape: const ContinuousRectangleBorder(
side: BorderSide(color: Colors.black, width: 2),
),
constraints: BoxConstraints(
minWidth: MediaQuery.of(context).size.width,
minHeight: 20.0),
padding: const EdgeInsets.all(12.0)),
Container(
color: Colors.blue,
width: MediaQuery.of(context).size.width,
height: 200,
alignment: Alignment.center,
padding: const EdgeInsets.all(20.0),
// child: ,
),
const Text(
"hello",
style: TextStyle(fontSize: 50),
textAlign: TextAlign.center,
),
Container(
color: Colors.blue,
width: MediaQuery.of(context).size.width,
height: 200,
alignment: Alignment.center,
padding: const EdgeInsets.all(20.0),
// child: ,
),
],
),
),
));
}
}
Correctly positioned background image(the black infinity)
Incorrectly positioned background image within a NavigatorPage(the black infinity)

How to adjust widget overflow error in flutter

i am really new to flutter , trying to learn designing part. whatever i did to adjust the size of the form its not getting into shape. its showing overflow error and not showing form full screen.
class CustomerInfo extends StatefulWidget {
#override
_CustomerInfoState createState() => _CustomerInfoState();
}
class _CustomerInfoState extends State<CustomerInfo> {
TextEditingController customername =
TextEditingController(text: 'Customer Name');
TextEditingController customerid = TextEditingController(text: 'CR20211212');
TextEditingController customertype = TextEditingController(text: 'CR');
TextEditingController contactno = TextEditingController(text: '12345678');
TextEditingController contactperson =
TextEditingController(text: 'Person to Contact');
TextEditingController contactpersonposition =
TextEditingController(text: 'Position of the Person');
TextEditingController mobileno = TextEditingController(text: '12345678');
TextEditingController tradelicense = TextEditingController(text: 'TR1000');
TextEditingController trdExpiry = TextEditingController(text: '2021/12/12');
TextEditingController place = TextEditingController(text: 'Location');
TextEditingController TRN = TextEditingController(text: '100012345123450');
TextEditingController notes = TextEditingController(text: 'Some notes');
TextEditingController active = TextEditingController(text: 'Customer Active');
#override
Widget build(BuildContext context) {
Widget subTitle = Padding(
padding: const EdgeInsets.only(right: 56.0, top: 0.0),
child: Text(
'Limited information only you can modify!!!',
style: TextStyle(
color: Colors.white,
fontSize: 14.0,
),
));
Widget registerButton = Positioned(
left: MediaQuery.of(context).size.width / 4,
child: Container(
width: MediaQuery.of(context).size.width / 2,
height: 30,
child: Center(
child: new Text("Update",
style: const TextStyle(
color: const Color(0xfffefefe),
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal,
fontSize: 16.0))),
decoration: BoxDecoration(
color: Colors.blueGrey,
boxShadow: [
BoxShadow(
color: Color.fromRGBO(0, 0, 0, 0.16),
offset: Offset(0, 5),
blurRadius: 10.0,
)
],
borderRadius: BorderRadius.circular(9.0)),
),
);
Widget registerForm = Container(
height: MediaQuery.of(context).size.height / 2,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.only(left: 32.0, right: 12.0),
decoration: BoxDecoration(
color: Color.fromRGBO(255, 255, 255, 0.8),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
bottomLeft: Radius.circular(10))),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: TextField(
controller: customername,
style: TextStyle(fontSize: 16.0),
decoration:
InputDecoration(labelText: 'Customer Name'),
enabled: false,
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: TextField(
controller: customerid,
style: TextStyle(fontSize: 16.0),
decoration: InputDecoration(labelText: 'Customer ID'),
enabled: false,
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: TextField(
controller: contactno,
style: TextStyle(fontSize: 16.0),
decoration: InputDecoration(labelText: 'Contact No'),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: TextField(
controller: contactperson,
style: TextStyle(fontSize: 16.0),
decoration:
InputDecoration(labelText: 'Contact Person'),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: TextField(
controller: contactpersonposition,
style: TextStyle(fontSize: 16.0),
decoration: InputDecoration(
labelText: 'Contact Person Position'),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: TextField(
controller: mobileno,
style: TextStyle(fontSize: 16.0),
decoration: InputDecoration(labelText: 'Mobile No'),
),
),
],
),
),
],
)));
Widget socialRegister = Column(
children: <Widget>[
Text(
'Please take approval for any kind of other modifications!!!',
style: TextStyle(
fontSize: 12.0, fontStyle: FontStyle.italic, color: Colors.white),
),
],
);
return Scaffold(
appBar: AppBar(
title: Text('Customer Information'),
centerTitle: true,
backgroundColor: Colors.blue.shade200,
),
backgroundColor: Colors.white70,
body: Stack(
children: <Widget>[
Container(
// Padding(
alignment: Alignment.topRight,
padding: const EdgeInsets.only(left: 28.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
subTitle,
SizedBox(height: 10),
// Expanded(child: Container(child: registerForm)),
registerForm,
Container(
alignment: Alignment.bottomRight,
child: registerButton,
),
Spacer(flex: 2),
Padding(
padding: EdgeInsets.only(bottom: 5), child: socialRegister)
],
),
)
],
),
);
}
}
Trying to show some customer details and some information change from user side.i tried to use expand and tried manually put the height also.
Try below code hope its help to you. add your Column inside SingleChildScrollView() and remove Spacer
Refer my answer here
Refer SingleChildScrollView here
body: SingleChildScrollView(
child:Column(
children:[
//Declare Your Widgets Here
],
),
),
Updated code:
Widget registerButton = Container(
width: MediaQuery.of(context).size.width / 2,
height: 30,
child: Center(
child: new Text("Update",
style: const TextStyle(
color: const Color(0xfffefefe),
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal,
fontSize: 16.0))),
decoration: BoxDecoration(
color: Colors.blueGrey,
boxShadow: [
BoxShadow(
color: Color.fromRGBO(0, 0, 0, 0.16),
offset: Offset(0, 5),
blurRadius: 10.0,
)
],
borderRadius: BorderRadius.circular(9.0)),
);
wrap you column with SingleChildScrollView and remove spacer() and use expanded because SingleChildScrollView make container height infinity

Flutter Dismissible background goes up after list item is dismissed

I just started learning flutter and am trying to build a todo app, the problem I encountered was the widget buildActionSwipeLeft() set as dismissible background goes up rather than left to right after the list item is dismissed although I set the direction of the dismissible from left to right or start to end. Any help would be appreciated.
My code:
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
),
color: const Color(0xfff6f6f6f6),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(bottom: 32.0, top: 32.0),
child: const Text(
"Reminders",
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold
),
),
),
Expanded(
child: ListView.builder(
itemCount: todos.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.only(
bottom: 15.0
),
child: Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 4,
child: ClipRRect(
clipBehavior: Clip.antiAlias,
child: Dismissible(
background: buildActionSwipeLeft(),
onDismissed: (direction) {
setState(() {
todos.removeAt(index);
_titleController.removeAt(index);
_detailController.removeAt(index);
});
},
direction: DismissDirection.startToEnd,
key: UniqueKey(),
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 13.0,
horizontal: 24.0
),
margin: const EdgeInsets.only(
bottom: 20.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
cursorColor: Colors.black,
controller: _titleController[index],
style: const TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold
),
decoration: const InputDecoration(
hintText: "Enter a title",
border: InputBorder.none,
),
),
const Divider(
color: Colors.black,
),
Padding(
padding: const EdgeInsets.only(top: 0.0),
child: TextField(
controller: _detailController[index],
style: TextStyle(
fontSize: 20.0,
color: Colors.grey[900],
),
cursorColor: Colors.black,
maxLines: null,
decoration: const InputDecoration(
hintText: "Enter the description",
label: Text("description"),
border: InputBorder.none
),
),
),
],
),
),
),
),
),
);
},
),
)
],
),
Positioned(
bottom: 24.0,
right: 0.0,
child: GestureDetector(
onTap: () {
setState(() {
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
});
},
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.circular(20.0),
),
child: const Icon(Icons.add, color: Colors.white, size: 35.0),
),
),
)
],
),
),
),
);
}
}
Widget buildActionSwipeLeft() => Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.0),
color: Colors.redAccent,
),
padding: const EdgeInsets.symmetric(horizontal: 30),
child: const Icon(Icons.delete, color: Colors.white, size: 30),
);
I figured out that this was not an issue as this is the default animation thats played when a list tile wrapped in a dismissible widget is dismissed. And the dismiss direction just determines the direction in which you can swipe the widget and not the direction in which the widget animates after dismissal.

Dismissible container and ListView item not the same size

I just started learning flutter and am trying to build a todo app, the problem I encountered was the Dismissible container and the todo list view item have different heights and after trying everything I still couldn't fix it, the next problem was that the todo item would be dismissed from left to right whereas the container would go up. Any help would be much appreciated. My code:
class _HomePageState extends State<HomePage> {
List todos = [];
List<TextEditingController> _titleController = [];
List<TextEditingController> _detailController = [];
#override
void initState() {
super.initState();
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
),
color: const Color(0xfff6f6f6f6),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(bottom: 32.0, top: 32.0),
child: const Text(
"Reminders",
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold
),
),
),
Expanded(
child: ListView.builder(
itemCount: todos.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Dismissible(
background: buildActionSwipeLeft(),
onDismissed: (direction) {
setState(() {
todos.removeAt(index);
_titleController.removeAt(index);
_detailController.removeAt(index);
DismissDirection.startToEnd;
});
},
direction: DismissDirection.startToEnd,
key: Key(todos[index]),
child: Padding(
padding: const EdgeInsets.only(
bottom: 15.0
),
child: Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 4,
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 24.0
),
margin: const EdgeInsets.only(
bottom: 20.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
cursorColor: Colors.black,
controller: _titleController[index],
style: const TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold
),
decoration: const InputDecoration(
hintText: "Enter a title",
border: InputBorder.none,
),
),
const Divider(
color: Colors.black,
),
Padding(
padding: const EdgeInsets.only(top: 0.0),
child: TextField(
controller: _detailController[index],
style: TextStyle(
fontSize: 20.0,
color: Colors.grey[900],
),
cursorColor: Colors.black,
maxLines: null,
decoration: const InputDecoration(
hintText: "Enter the description",
label: Text("description"),
border: InputBorder.none
),
),
),
],
),
),
),
),
);
},
),
)
],
),
Positioned(
bottom: 24.0,
right: 0.0,
child: GestureDetector(
onTap: () {
setState(() {
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
});
},
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.circular(20.0),
),
child: const Icon(Icons.add, color: Colors.white, size: 35.0),
),
),
)
],
),
),
),
);
}
}
Widget buildActionSwipeLeft() => Container(
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: Colors.red,
),
padding: const EdgeInsets.symmetric(horizontal: 30),
child: const Icon(Icons.delete, color: Colors.white, size: 30),
);
class _HomePageState extends State<HomePage> {
List todos = [];
List<TextEditingController> _titleController = [];
List<TextEditingController> _detailController = [];
#override
void initState() {
super.initState();
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
),
color: const Color(0xfff6f6f6f6),
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(bottom: 32.0, top: 32.0),
child: const Text(
"Reminders",
style: TextStyle(
fontSize: 25.0, fontWeight: FontWeight.bold),
),
),
Expanded(
child: ListView.builder(
itemCount: todos.length,
physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Stack(
clipBehavior: Clip.hardEdge,
children: [
Padding(
padding: const EdgeInsets.only(top:10.0,left: 8.0, right: 8.0),
child: buildActionSwipeLeft(),
),
Dismissible(
onDismissed: (direction) {
setState(() {
todos.removeAt(index);
_titleController.removeAt(index);
_detailController.removeAt(index);
DismissDirection.startToEnd;
});
},
direction: DismissDirection.startToEnd,
key: UniqueKey(),
child: Padding(
padding: const EdgeInsets.only(bottom: 15.0),
child: Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 4,
child: Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 15.0, horizontal: 24.0),
margin: const EdgeInsets.only(
bottom: 20.0,
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
TextField(
cursorColor: Colors.black,
controller: _titleController[index],
style: const TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold),
decoration: const InputDecoration(
hintText: "Enter a title",
border: InputBorder.none,
),
),
const Divider(
color: Colors.black,
),
Padding(
padding:
const EdgeInsets.only(top: 0.0),
child: TextField(
controller:
_detailController[index],
style: TextStyle(
fontSize: 20.0,
color: Colors.grey[900],
),
cursorColor: Colors.black,
maxLines: null,
decoration: const InputDecoration(
hintText:
"Enter the description",
label: Text("description"),
border: InputBorder.none),
),
),
],
),
),
),
),
)
],
);
},
),
)
],
),
Positioned(
bottom: 24.0,
right: 0.0,
child: GestureDetector(
onTap: () {
setState(() {
todos.add('');
_titleController.add(TextEditingController());
_detailController.add(TextEditingController());
});
},
child: Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
color: Colors.black87,
borderRadius: BorderRadius.circular(20.0),
),
child:
const Icon(Icons.add, color: Colors.white, size: 35.0),
),
),
)
],
),
),
),
);
}
}
Widget buildActionSwipeLeft() => Container(
height: 180,
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: Colors.red,
),
padding: const EdgeInsets.only(left: 30),
child: const Icon(Icons.delete, color: Colors.white, size: 30),
);
Achieving this has a disadvantage of loosing a few animation. Will research more:

Showing a snackbar in Flutter

i am working on signin part of my project and i had a form with email and password and a sign in button and everything is working it is connecting to the firebase. It's sending me the result either success or an error. What i want to ask is that i would like to show the error in snack bar and i have been trying all day but it doesnt work. Can any one please help!! the error message am getting is below,
FlutterError (Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer stable.
To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling inheritFromWidgetOfExactType() in the widget's didChangeDependencies() method.)
and here's the code
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:inclass/screens/authentication/signup.dart';
import 'package:inclass/screens/home/dashboard.dart';
import 'package:inclass/services/auth.dart';
import 'package:inclass/shared/loading.dart';
import 'package:inclass/widgets/logo.dart';
class Signin extends StatefulWidget {
#override
_SigninState createState() => _SigninState();
}
class _SigninState extends State<Signin> {
bool _obscureText = true;
final AuthService _auth = AuthService();
final _formkey = GlobalKey<FormState>();
bool loading = false;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
String email = '';
String password = '';
String error = '';
#override
Widget build(BuildContext context) {
return loading
? Loading()
: Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
body: Builder(
builder: (context) => ListView(children: <Widget>[
Form(
key: _formkey,
child: Column(
children: <Widget>[
Logo(),
SizedBox(
height: 20.0,
),
Stack(children: <Widget>[
Image(
height: 200.0,
width: MediaQuery.of(context).size.width,
image: AssetImage("assets/images/move.png"),
fit: BoxFit.cover,
),
Positioned(
bottom: 20.0,
right: 60.0,
child: Text(
'Sign In',
style: TextStyle(
color: Color(0xff7E8E9D),
fontSize: 22.0,
fontFamily: 'Poppins'),
textAlign: TextAlign.center,
)),
Positioned(
bottom: 5.0,
right: 80.0,
child: Text(
"As",
style: TextStyle(
color: Color(0xff7E8E9D),
fontSize: 15.0,
fontFamily: 'Poppins'),
textAlign: TextAlign.center,
),
)
]),
Padding(
padding: const EdgeInsets.only(
top: 20.0, left: 15.0, right: 15.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width / 3,
height: 80.0,
decoration: new BoxDecoration(
//border: new Border.all(width: 1.0, color: Colors.black),
//shape: BoxShape.circle,
color: Colors.white,
boxShadow: <BoxShadow>[
// BoxShadow(
// color: Colors.grey,
// offset: Offset(1.0, 15.0),
// blurRadius: 64.0,
// ),
],
),
// color: Colors.blue,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
FontAwesomeIcons.graduationCap,
color: Color(0xffB57E20),
size: 22.0,
),
Padding(
padding:
const EdgeInsets.only(left: 15.0),
child: Text(
"Student",
style: TextStyle(
color: Color(0xffB57E20),
fontSize: 17.0,
fontFamily: 'Poppins'),
),
)
],
),
),
Container(
width: 1.0,
height: 60.0,
decoration: BoxDecoration(
border: Border(
right: BorderSide(color: Colors.black54),
),
),
),
Container(
width: MediaQuery.of(context).size.width / 3,
height: 80.0,
decoration: new BoxDecoration(
//border: new Border.all(width: 1.0, color: Colors.black),
//shape: BoxShape.circle,
color: Colors.white,
boxShadow: <BoxShadow>[
// BoxShadow(
// color: Colors.grey,
// offset: Offset(1.0, 15.0),
// blurRadius: 64.0,
// ),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
FontAwesomeIcons.chalkboardTeacher,
color: Color(0xff00315C),
size: 22.0,
),
Padding(
padding:
const EdgeInsets.only(left: 15.0),
child: Text(
"Teacher",
style: TextStyle(
color: Color(0xff00315C),
fontSize: 17.0,
fontFamily: 'Poppins'),
),
)
],
),
)
],
),
),
),
Container(
child: Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0, top: 40.0),
child: TextFormField(
onChanged: (val) {
setState(() => email = val);
},
validator: (val) =>
val.isEmpty ? "Email can't be Empty" : null,
// textAlign: TextAlign.center,
keyboardType: TextInputType.emailAddress,
// autofocus: true,
decoration: InputDecoration(
labelText: "Email",
contentPadding:
EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0),
borderSide:
BorderSide(color: Color(0xff00315C))),
suffixIcon: Icon(Icons.mail)),
),
),
),
Padding(
padding: const EdgeInsets.only(
top: 15.0, left: 20.0, right: 20.0, bottom: 20.0),
child: TextFormField(
obscureText: _obscureText,
onChanged: (val) {
setState(() => password = val);
},
validator: (val) => val.length < 6
? "Password Must be 6+ Char"
: null,
// textAlign: TextAlign.center,
// autofocus: true,
decoration: InputDecoration(
labelText: "Password",
contentPadding:
EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0),
borderSide:
BorderSide(color: Color(0xff00315C))),
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child: Icon(
_obscureText
? Icons.visibility
: Icons.visibility_off,
semanticLabel: _obscureText
? 'show password'
: 'hide password',
),
)),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 20.0),
child: FlatButton(
child: Text("Forgot Password?",
style: TextStyle(color: Colors.grey)),
onPressed: () {},
),
),
Padding(
padding: const EdgeInsets.only(right: 25.0),
child: OutlineButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
highlightedBorderColor: Color(0xffB57E20),
borderSide: BorderSide(color: Color(0xffB57E20)),
onPressed: () async {
if (_formkey.currentState.validate()) {
setState(() => loading = true);
dynamic result =
await _auth.signInWithEmailAndPassword(
email, password);
if (result == null) {
setState(() {
error = 'Could not sign in';
loading = false;
});
_showToast(context,error);
print(error);
} else {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (_) => DashBoard()));
print("Succeed");
}
}
},
padding: EdgeInsets.only(
left: 30.0,
right: 15.0,
top: 12.0,
bottom: 12.0),
color: Colors.white,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
"Next",
style: TextStyle(
color: Color(0xffB57E20),
fontSize: 17.0,
fontFamily: 'Poppins'),
),
Padding(
padding: const EdgeInsets.only(
left: 10.0, top: 2.0),
child: Icon(Icons.navigate_next,
color: Color(0xffB57E20), size: 30.0),
)
],
),
),
)
],
),
Padding(
padding: const EdgeInsets.all(28.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Not Registered Yet?",
style: TextStyle(
color: Colors.grey,
fontSize: 15.0,
fontFamily: 'Poppins')),
SizedBox(
width: 10.0,
),
GestureDetector(
onTap: () => Navigator.push(context,
MaterialPageRoute(builder: (_) => SignUp())),
child: Text("Sign Up",
style: TextStyle(
color: Color(0xff00315C),
fontSize: 15.0,
fontFamily: 'Poppins')),
),
],
),
)
],
),
),
]),
),
);
}
void _showToast(BuildContext context,String error) {
final scaffold = Scaffold.of(context);
scaffold.showSnackBar(SnackBar(
content: Text(error),
duration: Duration(seconds: 2),
action: SnackBarAction(
onPressed: () {
scaffold.hideCurrentSnackBar();
},
label: 'Okay',
),
));
}
}
My code is a little bit messy i didn't refactor it yet
It is related to this part of your code
return
loading
? Loading()
: Scaffold(
when you tap on Next button, you put code like this for loading
setState(() => loading = true);
and it removes Scaffold from Widget tree. and when you are trying to use _showToast function, though you called setState loading = false again, the Scaffold is not ready and moved into Widget tree, so Scaffold.of cannot make proper result you want.
So I offer you if you want to show loading screen, you should use Dialog or IndexedStack.
Hope this can solve your problem.