Hi I'm routing menu with Drawer. It works fine for 2 pages but there is one page gives error.
The menu works correctly when I first press it, then when I go to another page and come back it gives this error
Also I tryed routing with routes on mainApp buut this way seemed easier to me
My drawer
class MyDrawer extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MyDrawerState();
}
class _MyDrawerState extends State {
#override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
children: <Widget>[
DrawerHeader(
child: Align(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Test",
style: TextStyle(color: Colors.white, fontSize: 25.0),
),
],
),
),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
leading: Icon(Icons.home),
title: Text('Main'),
trailing: Icon(Icons.arrow_right),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Main(),
));
},
),
ListTile(
leading: Icon(Icons.perm_device_information),
title: Text('How'),
trailing: Icon(Icons.arrow_right),
onTap: () {
//Navigator.pushNamed(context, "/how");
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HowItWorks(),
));
},
),
ListTile(
leading: Icon(Icons.keyboard),
title: Text('Contact'),
trailing: Icon(Icons.arrow_right),
onTap: () {
//Navigator.pushNamed(context, "/contact");
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SendMail(),
));
},
),
],
),
);
}
}
this is the page it gives error on second route and drawer is not visible
final _formKey2 = GlobalKey<FormState>();
class SendMail extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: MyDrawer(),
body: Center(
child: Form(
key: _formKey2,
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(48.0),
child: Text(
'İletişim',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Text('Contact Me'),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
keyboardType: TextInputType.text,
validator: (value) {
if (value.isEmpty) {
return 'Can not be empty';
}
return null;
},
decoration: InputDecoration(
filled: true,
hintText: 'Name',
border: InputBorder.none),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
filled: true,
hintText: 'Email',
border: InputBorder.none),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
maxLines: 7,
validator: (value) {
if (value.isEmpty) {
return 'Can not be empty';
}
return null;
},
decoration: InputDecoration(
filled: true,
hintText: 'Message',
border: InputBorder.none),
),
),
],
),
)
],
),
Detailed error
Related
It won't allow me to change the radio button inside the form, the value also does not change no matter what is selected. I have tried the code outside the form and it works fine but when i put it inside the form then it stops working for reasons I do not know.
FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('New User'),
content: Stack(
children: <Widget>[
Positioned(
right: -40.0,
top: -40.0,
child: InkResponse(
onTap: () {
Navigator.of(context).pop();
},
child: CircleAvatar(
child: Icon(Icons.close),
backgroundColor: Colors.blue,
),
),
),
Form(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
controller: nameController,
decoration: InputDecoration(
labelText: 'Name',
),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
controller: surnameController,
decoration: InputDecoration(
labelText: 'Surname',
),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
controller: userController,
decoration: InputDecoration(
labelText: 'Username',
),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
controller: passController,
decoration: InputDecoration(
labelText: 'Password',
),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
controller: mobileController,
decoration: InputDecoration(
labelText: 'Mobile num',
),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
controller: emailController,
decoration: InputDecoration(
labelText: 'Email',
),
),
),
//radioButtons
Container(
padding: EdgeInsets.all(20),
child: Column(
children: [
Text(
"What is your gender?",
style: TextStyle(fontSize: 18),
),
Divider(),
RadioListTile(
title: Text("Male"),
value: "male",
groupValue: gender,
onChanged: (value) {
setState(() {
gender = value.toString();
});
},
),
RadioListTile(
title: Text("Female"),
value: "female",
groupValue: gender,
onChanged: (value) {
setState(() {
gender = value.toString();
});
},
),
RadioListTile(
title: Text("Other"),
value: "other",
groupValue: gender,
onChanged: (value) {
setState(() {
gender = value.toString();
});
},
)
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: FloatingActionButton(
child: Text("Submit"),
onPressed: () {
//createUser();
print(gender);
Navigator.pop(context);
},
),
)
],
),
),
),
],
),
);
});
},
child: Icon(Icons.person),
backgroundColor: Colors.blue,
),
it has a few text fields and then the radio buttons, the gender variable is declared as a string.
It's Because you are assigned a value in the dialog. Just Wrap Your Alert Dialog Widget with statfulBuilder and then stateState.
example
FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return AlertDialog(
title: const Text('New User'),
content: Stack(
children: <Widget>[
Positioned(
right: -40,
top: -40,
child: InkResponse(
onTap: () {
Navigator.of(context).pop();
},
child: const CircleAvatar(
backgroundColor: Colors.blue,
child: Icon(Icons.close),
),
),
),
Form(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: nameController,
decoration: const InputDecoration(
labelText: 'Name',
),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: surnameController,
decoration: const InputDecoration(
labelText: 'Surname',
),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: userController,
decoration: const InputDecoration(
labelText: 'Username',
),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: passController,
decoration: const InputDecoration(
labelText: 'Password',
),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: mobileController,
decoration: const InputDecoration(
labelText: 'Mobile num',
),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: emailController,
decoration: const InputDecoration(
labelText: 'Email',
),
),
),
//radioButtons
Container(
padding: const EdgeInsets.all(20),
child: Column(
children: [
const Text(
'What is your gender?',
style: TextStyle(fontSize: 18),
),
const Divider(),
RadioListTile(
title: const Text('Male'),
value: 'male',
groupValue: gender,
onChanged: (value) {
setState(() {
gender = value.toString();
});
},
),
RadioListTile(
title: const Text('Female'),
value: 'female',
groupValue: gender,
onChanged: (value) {
setState(() {
gender = value.toString();
});
},
),
RadioListTile(
title: const Text('Other'),
value: 'other',
groupValue: gender,
onChanged: (value) {
setState(() {
gender = value.toString();
});
},
)
],
),
),
Padding(
padding: const EdgeInsets.all(8),
child: FloatingActionButton(
child: const Text('Submit'),
onPressed: () {
//createUser();
print(gender);
Navigator.pop(context);
},
),
)
],
),
),
),
],
),
);
},
);
},
);
},
backgroundColor: Colors.blue,
child: Icon(Icons.person),
);
I am building a flutter project on both app and web. I am having a couple of issues with the login page. First my column widget fills the whole width on Flutter web but I want it to be more central. Secondly I am trying to center align the Don't have an account? Sign up button which has found itself aligning to the left. Please may someone assist. Here's my code and a couple of screenshots
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Center(
child: Card(
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
validator: (value) =>
value!.isEmpty ? 'Email cannot be empty' : null,
onSaved: (value) => _email = value!,
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
labelText: 'Email',
hintText: 'Email',
border: OutlineInputBorder(),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
validator: (value) =>
value!.isEmpty ? 'Password cannot be empty' : null,
onSaved: (value) => _password = value!,
decoration: const InputDecoration(
filled: true,
fillColor: Colors.white,
labelText: 'Password',
hintText: 'Password',
border: OutlineInputBorder(),
),
obscureText: true,
),
),
Padding(
padding: const EdgeInsets.all(0),
child: TextButton(
onPressed: () {
Navigator.pushNamed(context, '/resetpassword');
},
child: const Text('Forgot Password?'),
style: TextButton.styleFrom(
primary: Colors.black,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: validateAndSubmit,
child: const Text('Login'),
style: ElevatedButton.styleFrom(
primary: Colors.black,
onSurface: Colors.black,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Text('Dont have an account?'),
TextButton(
onPressed: () {
Navigator.pushNamed(context, '/signup');
},
child: const Text(
'Signup',
style: TextStyle(fontWeight: FontWeight.bold),
),
style: TextButton.styleFrom(
primary: Colors.black,
),
),
],
),
),
],
),
),
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
To center the 'Dont have an account?' text and 'Signup' TextButton,
use mainAxisAlignment in Row.
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,//<-- this
children: [
const Text('Dont have an account?'),
TextButton(
onPressed: () {
Navigator.pushNamed(context, '/signup');
},
child: const Text(
'Signup',
style: TextStyle(fontWeight: FontWeight.bold),
),
style: TextButton.styleFrom(
primary: Colors.black,
),
),
],
),
),
To responsive web and app,
I use this method,
void main() async {
runApp(
const ResponsiveLayout(),
);
}
In my ResponsiveLayout const webScreenSize = 600;
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > webScreenSize) {
//webscreen
return widget.webScreenLayout; // <-- send user Web screen
} else {
//mobile screen
return widget.mobileScreenLayout; // <-- send user mobile screen
}
},
);
}
Read more about LayoutBuilder -
https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html
When the keyboard appears the fab is placed in the middle of the screen instead of staying on board the keyboard
There is a lot of post on this subject on the web, but I cannot find the adequate solution to mine.
Here is the code.
Widget build(BuildContext context) {
final isKeyboard = MediaQuery.of(context).viewInsets.bottom != 0;
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
iconTheme: const IconThemeData(color: Colors.black),
backgroundColor: Colors.transparent,
//****************************** EDITBUTTON ***************************** */
elevation: 0,
actions: [
IconButton(
onPressed: () async {
await Databahelper.instance.deleteNote(widget.note!.id!);
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const StickyNote()));
},
icon: const Icon(Icons.delete)),
//*************************** DELETE_BUTTON ***************************** */
],
),
body: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
const SizedBox(height: 8),
TextField(
maxLines: 1,
controller: titleController,
decoration: const InputDecoration(
label: Text(
'Title',
style: TextStyle(fontSize: 20),
),
),
),
const SizedBox(
height: 30,
),
Expanded(
child: TextField(
keyboardType: TextInputType.multiline,
controller: descController,
maxLines: null,
decoration: const InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.all(10),
hintText: "Enter Your Text...",
hintStyle: TextStyle(
fontSize: 12,
color: Colors.purple,
fontStyle: FontStyle.italic,
),
),
),
)
],
),
),
//---------------------------bottomNavigation --------------------------------------
bottomNavigationBar: Visibility(
visible: !isKeyboard,
child: BottomAppBar(
elevation: 4,
color: backgroundColor,
child: SizedBox(
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.add_box_outlined)),
const Text('July 2050'),
IconButton(
onPressed: () {}, icon: const Icon(Icons.more_vert)),
],
),
),
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
setState(() {
title = titleController.text;
description = descController.text;
});
NotedB notelocal = NotedB(title: title, description: description);
addNote(notelocal);
Navigator.push(
context, MaterialPageRoute(builder: (_) => const StickyNote()));
},
label: const Text('Save note'),
icon: const Icon(Icons.note_add_outlined),
));
}
screenshot
The validator is not showing the error message while I try to click the button without entering anything in the box and even after filling the box the bottom doesn't take me to the next screen.
return Scaffold(
appBar: AppBar(
title: Text("Feedback Form"),
),
body: Container(
child: Center(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 50, vertical: 40),
child: TextFormField(
validator: (String value) {
if (value.isEmpty) {
return "Name is required";
}
return null;
},
decoration: InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Enter your Name'),
),
),
ButtonTheme(
child: ElevatedButton(
child: Text("Next"),
onPressed: () {
if (!_formKey.currentState.validate()) {
return;
}
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
},
style: ElevatedButton.styleFrom(
padding:
EdgeInsets.symmetric(horizontal: 25, vertical: 15),
),
),
),
],
),
),
));
}
}
you forget the Form widget
return Scaffold(
appBar: AppBar(
title: Text("Feedback Form"),
),
body: Container(
child: Center(
child: Form( // add this
autovalidateMode: AutovalidateMode.onUserInteraction, // this to show error when user is in some textField
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 50, vertical: 40),
child: TextFormField(
validator: (String value) {
if (value.isEmpty) {
return "Name is required";
}
return null;
},
decoration: InputDecoration(
border: UnderlineInputBorder(),
labelText: 'Enter your Name'),
),
),
ButtonTheme(
child: ElevatedButton(
child: Text("Next"),
onPressed: () {
if (_formKey.currentState.validate()) { // to check if the form is validate then navigate
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondScreen()),
);
}
},
style: ElevatedButton.styleFrom(
padding:
EdgeInsets.symmetric(horizontal: 25, vertical: 15),
),
),
),
],
),
),
)));
Add Form as the child of the Center Widget
I'm having trouble placing my search bar in the AppBar,
right now my searchBar is below my AppBar, I tried use another Container into my AppBar but without success.
My code:
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home:Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(100.0),
child: AppBar(
iconTheme: IconThemeData(color: Color.fromRGBO(9, 133, 46, 100)),
backgroundColor: Colors.white,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.shopping_cart,
color: Color.fromRGBO(9, 133, 46, 100),
),
onPressed: (){
print('klikniete');
},
),
],
),
),
body: Builder(
builder: (context) => Container(
child: FutureBuilder(
future: fetchOrders(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (_ordersForDisplay.length == null) {
return Container(
child: Center(child: Text("Ładowanie...")),
);
} else {
return ListView.builder(
itemCount: _ordersForDisplay.length + 1,
itemBuilder: (BuildContext context, int index) {
return index == 0 ? _searchBar() : _listItem(index - 1);
},
);
}
},
),
),
),
)
);
}
_searchBar() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(
hintText: 'Wyszukaj po mieście...'
),
onChanged: (text) {
text = text.toLowerCase();
setState(() {
_ordersForDisplay = _orders.where((note) {
var noteTitle = note.city.toLowerCase();
return noteTitle.contains(text);
}).toList();
});
},
),
);
}
_listItem(index) {
return GestureDetector(
onTap: () => Navigator.of(context).push(
MaterialPageRoute(builder: (context) => DetailPage(item: _ordersForDisplay[index])),
),
child: Card(
child: Padding(
padding: const EdgeInsets.only(
top: 32.0, bottom: 32.0, left: 16.0, right: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
_ordersForDisplay[index].firstName,
style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
),
Text(
_ordersForDisplay[index].lastName,
style: TextStyle(
color: Colors.grey.shade600
),
),
],
),
),
),
);
}
}
i'm put searchBar into my appBar by use title: _searchBar, next I remove
return index == 0 ? _searchBar() : _listItem(index - 1); and paste only return _listItem(index, context), but right now i have error: RangeError (index): Invalid value: Only valid value is 0: 1
Are you expecting to this
OR this?
Code:
class CustomSearchBarDemo extends StatefulWidget {
#override
_CustomSearchBarDemoState createState() => _CustomSearchBarDemoState();
}
class _CustomSearchBarDemoState extends State<CustomSearchBarDemo> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
backgroundColor: Colors.white,
title: Text("Search",style: TextStyle(color: Colors.black),),
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: Container(
// padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.grey[300],
),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Material(
color: Colors.grey[300],
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.search,color: Colors.grey),
Expanded(
child: TextField(
// textAlign: TextAlign.center,
decoration: InputDecoration.collapsed(
hintText: ' Search by name or address',
),
onChanged: (value) {
},
),
),
InkWell(
child: Icon(Icons.mic,color: Colors.grey,),
onTap: () {
},
)
],
),
),
)
) ,
),
),
);
}
}
OR
class CustomSearchBarDemo extends StatefulWidget {
#override
_CustomSearchBarDemoState createState() => _CustomSearchBarDemoState();
}
class _CustomSearchBarDemoState extends State<CustomSearchBarDemo> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:
PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: Container(
padding: const EdgeInsets.only(top:20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.grey[300],
),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Material(
color: Colors.grey[300],
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.search,color: Colors.grey),
Expanded(
child: TextField(
// textAlign: TextAlign.center,
decoration: InputDecoration.collapsed(
hintText: ' Search by name or address',
),
onChanged: (value) {
},
),
),
InkWell(
child: Icon(Icons.mic,color: Colors.grey,),
onTap: () {
},
)
],
),
),
)
) ,
),
);
}
}
You can basically add any widget in the title property of appbar.
AppBar(
title: TextField(
autofocus: true,
decoration: InputDecoration(
hintText: " Search...",
border: InputBorder.none,
suffixIcon: IconButton(icon:Icon(Icons.search), onPressed: () {
},)
),
style: TextStyle(color: Colors.white, fontSize: 14.0),
),
iconTheme: IconThemeData(color: Color.fromRGBO(9, 133, 46, 100)),
backgroundColor: Colors.white,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.shopping_cart,
color: Color.fromRGBO(9, 133, 46, 100),
),
onPressed: (){
print('klikniete');
},
),
],
),