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');
},
),
],
),
Related
For the following code, I am getting a pixel overflow whenever I am trying to open the keyboard to search for something in the search bar.
I cannot remove the container having the specified height of 500 because doing so produces other errors.
import 'package:chatapp/services/database.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class Search extends StatefulWidget {
_Search createState() => _Search();
}
class _Search extends State<Search> {
QuerySnapshot<Map<String, dynamic>>? searchResultSnapshot;
bool isLoading = false;
bool haveUserSearched = false;
DatabaseMethods databaseMethods = new DatabaseMethods();
var searchEditingController = TextEditingController();
InitiateSearch() async {
if (searchEditingController.text.isNotEmpty) {
setState(() {
isLoading = true;
});
await databaseMethods.GetUserByUsername(searchEditingController.text)
.then((snapshot) {
searchResultSnapshot = snapshot;
print("$searchResultSnapshot");
setState(() {
isLoading = false;
haveUserSearched = true;
});
});
}
}
Widget UserList() {
return Container(
height: 500,
child: isLoading
? Container(
child: Center(
child: CircularProgressIndicator(),
),
)
: ListView.builder(
itemCount: searchResultSnapshot?.docs.length ?? 0,
itemBuilder: (context, index) {
return ListTile(
searchResultSnapshot?.docs[index].data()["userName"],
searchResultSnapshot?.docs[index].data()["userEmail"],
);
}),
);
}
Widget ListTile(String? userName, String? userEmail) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
userName ?? "",
style: TextStyle(color: Colors.white, fontSize: 16),
),
Text(
userEmail ?? "",
style: TextStyle(color: Colors.white, fontSize: 16),
)
],
),
Spacer(),
GestureDetector(
onTap: () {
null;
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.circular(24)),
child: Text(
"Message",
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
)
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
titleSpacing: 0,
leading: Builder(
builder: (BuildContext context) {
return IconButton(
icon: const Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context);
});
},
),
title: Text('Search'),
),
body: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: [
Container(
height: 36,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10)),
boxShadow: [
BoxShadow(
color: Colors.black,
),
BoxShadow(
color: Colors.black,
spreadRadius: -12.0,
blurRadius: 12.0,
),
],
),
margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0),
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 0, horizontal: 10.0),
child: TextFormField(
style: TextStyle(color: Colors.black),
controller: searchEditingController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Search',
hintStyle: TextStyle(color: Colors.grey),
icon: GestureDetector(
onTap: () {
InitiateSearch();
},
child: GestureDetector(
onTap: () {
InitiateSearch();
print('tap');
},
child: Icon(
Icons.search,
color: Colors.grey,
),
),
),
suffixIcon: IconButton(
onPressed: searchEditingController.clear,
icon: Icon(
Icons.cancel_rounded,
color: Colors.grey,
),
),
),
),
),
), //Search
SizedBox(
height: 12,
),
UserList(),
],
),
));
}
}
Could anyone solve this? Also are there anyways to make the container height dynamic. Your help will be highly appreciated.
Okay I found the solution myself. Under UserList() I replaced:
return Container(...);
with:
return Expanded(...);
I have created a simple web page where I have two buttons, one to add a donor and the other to list the donors. When each of the button is clicked, I want the respective pages to open.
I click on the 'Add Donor' button, fill the form and click on 'Submit'. Then I click on 'List Donors' and return back to 'Add Donor', and on clicking on the 'Name' field', I get the below error when running this on Chrome Browser.
Error: A FocusNode was used after being disposed.
Once you have called dispose() on a FocusNode, it can no longer be used.
at Object.throw_ [as throw] (http://localhost:62365/dart_sdk.js:5334:11)
at http://localhost:62365/packages/flutter/src/foundation/change_notifier.dart.lib.js:83:21
at focus_manager.FocusNode.new.[_debugAssertNotDisposed] (http://localhost:62365/packages/flutter/src/foundation/change_notifier.dart.lib.js:86:25)
at focus_manager.FocusNode.new.notifyListeners (http://localhost:62365/packages/flutter/src/foundation/change_notifier.dart.lib.js:113:51)
at focus_manager.FocusNode.new.[_notify] (http://localhost:62365/packages/flutter/src/widgets/widget_span.dart.lib.js:47534:12)
at focus_manager.FocusManager.new.[_applyFocusChange] (http://localhost:62365/packages/flutter/src/widgets/widget_span.dart.lib.js:48310:26)
at Object._microtaskLoop (http://localhost:62365/dart_sdk.js:39176:13)
at _startMicrotaskLoop (http://localhost:62365/dart_sdk.js:39182:13)
at http://localhost:62365/dart_sdk.js:34689:9
This is my code snippet
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
BloodDonationPage(),
),
);
},
child: Scaffold(
body: Center(
child: Container(
width: 200,
height: 100,
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side:
BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Center(
child: Text(
"Blood Donation",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold),
)),
),
),
),
),
);
}
}
class BloodDonationPage extends StatefulWidget {
#override
_BloodDonationPageState createState() => _BloodDonationPageState();
}
class _BloodDonationPageState extends State<BloodDonationPage> {
bool _addButton = false;
bool _listButton = false;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 60,
//width: 600,
child: Card(
color: Colors.pink[50],
shadowColor: Colors.pink,
elevation: 20,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
GestureDetector(
onTap: () {
setState(() {
_addButton = true;
_listButton = false;
});
},
child: Padding(
padding: const EdgeInsets.only(left: 60, right: 30.0),
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side:
BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"Add Donor",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold),
)),
),
),
),
),
GestureDetector(
onTap: () {
setState(() {
_addButton = false;
_listButton = true;
});
},
child: Padding(
padding: const EdgeInsets.only(left: 60, right: 30.0),
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"List Donors",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
)),
),
),
),
),
],
),
),
),
_addButton ? Flexible(child: BloodDonorDetailPage()) : SizedBox.shrink(),
_listButton ? Flexible(child: ListBloodDonorPage()) : SizedBox.shrink(),
],
);
}
}
class BloodDonorDetailPage extends StatefulWidget {
#override
_BloodDonorDetailPageState createState() => _BloodDonorDetailPageState();
}
class _BloodDonorDetailPageState extends State<BloodDonorDetailPage> {
final _formKey = GlobalKey<FormBuilderState>();
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(30.0),
child: FormBuilder(
autovalidateMode: AutovalidateMode.disabled,
key: _formKey,
child: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
FormBuilderTextField(
autofocus: true,
name: 'name',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
FormBuilderValidators.maxLength(context, 50),
]),
decoration: InputDecoration(labelText: 'Name'),
),
FormBuilderTextField(
name: 'phone',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
FormBuilderValidators.minLength(context, 10),
FormBuilderValidators.maxLength(context, 10),
FormBuilderValidators.numeric(context,
errorText: 'Mobile No should be 10 digits')
]),
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: 'Phone'),
),
FormBuilderChoiceChip(
name: 'gender',
elevation: 10,
selectedColor: Colors.white,
disabledColor: Colors.black12,
alignment: WrapAlignment.spaceAround,
options: ['M', 'F']
.map((value) => FormBuilderFieldOption(
value: value,
child: (value == 'M')
? Text('Male')
: Text('Female'),
))
.toList(),
decoration: InputDecoration(labelText: 'Gender'),
),
FormBuilderChoiceChip(
name: 'bloodGroup',
elevation: 10,
selectedColor: Colors.white,
disabledColor: Colors.black12,
alignment: WrapAlignment.spaceAround,
options: ['A+','O+']
.map((value) => FormBuilderFieldOption(value: value))
.toList(),
decoration: InputDecoration(labelText: 'Blood Group'),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MaterialButton(
color: Theme.of(context).accentColor,
child: Text('Submit',
style: TextStyle(color: Colors.white),
),
onPressed: () async {
//print(_formKey.currentState.mounted);
Map<String, dynamic> _donorMap;
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
//print(_formKey.currentState.value);
_donorMap = {
..._formKey.currentState.value,
'createdDate': DateTime.now()
};
print(_donorMap);
/*await BloodDonorsController()
.saveBloodDonors(widget.mode!, _donorMap);*/
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Add Donor Successful'),
),
);
_formKey.currentState.reset();
//FocusScope.of(context).requestFocus(focusNode);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Validation Failed'),
),
);
}
},
),
SizedBox(width: 20),
MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
"Reset",
style: TextStyle(color: Colors.white),
),
onPressed: () {
_formKey.currentState.reset();
},
),
],
),
)
],
),
),
),
);
}
}
class ListBloodDonorPage extends StatefulWidget {
#override
_ListBloodDonorPageState createState() => _ListBloodDonorPageState();
}
class _ListBloodDonorPageState extends State<ListBloodDonorPage> {
#override
Widget build(BuildContext context) {
return Container(child: Text('Display List of Donors'),);
}
}
What is the problem here?
Can anyone please help me?
I was able to finally solve this by converting the stateful widgets to methods and adding the Visibility widget to display the widget with the state maintained as shown below.
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
BloodDonationPage(),
),
);
},
child: Scaffold(
body: Center(
child: Container(
width: 200,
height: 100,
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side:
BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Center(
child: Text(
"Blood Donation",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold),
)),
),
),
),
),
);
}
}
class BloodDonationPage extends StatefulWidget {
#override
_BloodDonationPageState createState() => _BloodDonationPageState();
}
class _BloodDonationPageState extends State<BloodDonationPage> {
bool _addButton = false;
bool _listButton = false;
final _formKey = GlobalKey<FormBuilderState>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 60,
//width: 600,
child: Card(
color: Colors.pink[50],
shadowColor: Colors.pink,
elevation: 20,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
GestureDetector(
onTap: () {
setState(() {
_addButton = true;
_listButton = false;
});
},
child: Padding(
padding: const EdgeInsets.only(left: 60, right: 30.0),
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side:
BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"Add Donor",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold),
)),
),
),
),
),
GestureDetector(
onTap: () {
setState(() {
_addButton = false;
_listButton = true;
});
},
child: Padding(
padding: const EdgeInsets.only(left: 60, right: 30.0),
child: Card(
elevation: 20,
color: Colors.pink[100],
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.white70, width: 1),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Center(
child: Text(
"List Donors",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
)),
),
),
),
),
],
),
),
),
Visibility(visible: _addButton, maintainState: true,child: buildAdd()),
Visibility(visible: _listButton ,child: buildList()),
],
),
);
}
Widget buildList() => Container(child: Text('Display List of Donors'),);
Widget buildAdd() => Padding(
padding: const EdgeInsets.all(30.0),
child: Column( children: [ FormBuilder(
autovalidateMode: AutovalidateMode.disabled,
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
FormBuilderTextField(
autofocus: true,
name: 'name',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
FormBuilderValidators.maxLength(context, 50),
]),
decoration: InputDecoration(labelText: 'Name'),
),
FormBuilderTextField(
name: 'phone',
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
FormBuilderValidators.minLength(context, 10),
FormBuilderValidators.maxLength(context, 10),
FormBuilderValidators.numeric(context,
errorText: 'Mobile No should be 10 digits')
]),
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: 'Phone'),
),
FormBuilderChoiceChip(
name: 'gender',
elevation: 10,
selectedColor: Colors.white,
disabledColor: Colors.black12,
alignment: WrapAlignment.spaceAround,
options: ['M', 'F']
.map((value) => FormBuilderFieldOption(
value: value,
child: (value == 'M')
? Text('Male')
: Text('Female'),
))
.toList(),
decoration: InputDecoration(labelText: 'Gender'),
),
FormBuilderChoiceChip(
name: 'bloodGroup',
elevation: 10,
selectedColor: Colors.white,
disabledColor: Colors.black12,
alignment: WrapAlignment.spaceAround,
options: ['A+','O+']
.map((value) => FormBuilderFieldOption(value: value))
.toList(),
decoration: InputDecoration(labelText: 'Blood Group'),
),
],),),
SizedBox(height: 100,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MaterialButton(
color: Theme.of(context).accentColor,
child: Text('Submit',
style: TextStyle(color: Colors.white),
),
onPressed: () async {
//print(_formKey.currentState.mounted);
Map<String, dynamic> _donorMap;
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
//print(_formKey.currentState.value);
_donorMap = {
..._formKey.currentState.value,
'createdDate': DateTime.now()
};
print(_donorMap);
/*await BloodDonorsController()
.saveBloodDonors(widget.mode!, _donorMap);*/
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Add Donor Successful'),
),
);
_formKey.currentState.reset();
//FocusScope.of(context).requestFocus(focusNode);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Validation Failed'),
),
);
}
},
),
SizedBox(width: 20),
MaterialButton(
color: Theme.of(context).accentColor,
child: Text(
"Reset",
style: TextStyle(color: Colors.white),
),
onPressed: () {
_formKey.currentState.reset();
},
),
],
)
],
),
);
}
I am trying to create a page that consist of Search Bar, Infinite scroll product page and buttons (add product, remove product and notification). There is an error for the below statement...
The getter 'visible' was called on null,
Receiver : null,
Tried calling : null
please help me in rectifying this code.
class Inventory extends StatefulWidget {
#override
_InventoryState createState() => _InventoryState();
}
class _InventoryState extends State<Inventory> {
Color _color = Colors.white;
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: PreferredSize(
preferredSize: Size.fromHeight(70),
child: AppBar(
backgroundColor: Theme.Colors.darkBlue,
iconTheme: IconThemeData(size: 10, color: Colors.white),
elevation: 0,
title: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
AutoSizeText(
"Inventory ",
style: TextStyle(
fontSize: 35,
),
),
],
)),
),
drawer: MainDrawer(),
backgroundColor: Color(0xFF09182C),
body: Center(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
height: 70,
width: width * 0.76,
child: TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(10.0),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
hintText: 'Search Inventory',
hintStyle:
TextStyle(color: Color(0xFFE0E0E0), fontSize: 20),
suffixIcon: Icon(
Icons.search,
color: Colors.white,
size: 30,
)),
style: TextStyle(color: _color),
),
),
Container(
padding: EdgeInsets.only(bottom: 30.0),
child: IconButton(
onPressed: () {},
icon: Icon(Icons.filter_list,
size: 40, color: Color(0xFFFFAE40)),
),
),
],
),
LoadingPage(),
Spacer(),
Container(
margin: EdgeInsets.only(bottom: 70),
padding: EdgeInsets.only(left: 30, right: 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Material(
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(
border:
Border.all(color: Color(0xFF57D0F4), width: 2.0),
color: Colors.transparent,
shape: BoxShape.circle,
),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddProduct()),
);
},
child: Padding(
padding: EdgeInsets.all(13.0),
child: Icon(
Icons.add,
size: 55.0,
color: Color(0xFF57D0F4),
),
),
),
),
),
Material(
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(
border:
Border.all(color: Color(0xFF57D0F4), width: 2.0),
color: Colors.transparent,
shape: BoxShape.circle,
),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RemoveProduct()),
);
},
child: Padding(
padding: EdgeInsets.all(13.0),
child: Icon(
Icons.delete_outline,
size: 55.0,
color: Color(0xFF57D0F4),
),
),
),
),
),
Material(
type: MaterialType.transparency,
child: Ink(
decoration: BoxDecoration(
border:
Border.all(color: Color(0xFF57D0F4), width: 2.0),
color: Colors.transparent,
shape: BoxShape.circle,
),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Notify()),
);
},
child: Padding(
padding: EdgeInsets.all(13.0),
child: Icon(
Icons.notifications_none,
size: 55.0,
color: Color(0xFF57D0F4),
),
),
),
),
),
],
),
)
],
),
));
}
}
class LoadingPage extends StatefulWidget {
#override
_LoadingPageState createState() => _LoadingPageState();
}
class _LoadingPageState extends State<LoadingPage> {
List prd;
ScrollController _scrollController = ScrollController();
int _currentMax = 10;
#override
void initState() {
super.initState();
prd = List.generate(10, (i) => "Product ${i + 1}");
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_getMoreData();
}
});
}
_getMoreData() {
for (int i = _currentMax; i < _currentMax + 10; i++) {
return prd.add("Product ${i + 1}");
}
_currentMax = _currentMax + 10;
setState(() {});
}
#override
Widget build(BuildContext context) {
return ListView.builder(
controller: _scrollController,
itemCount: prd.length + 1,
itemExtent: 70,
itemBuilder: (context, i) {
if (i == prd.length) {
return CupertinoActivityIndicator();
}
return ListTile(
title: AutoSizeText(prd[i]),
);
});
}
}
Thanks for your help #Mobina and #JohnJoe.
I wrapped the ListView.builder with Flexible which fixed the problem and added COntainer to put it inside a greyish background.
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(top: 10.0, bottom: 10.0),
height: 450,
width: 350,
decoration: BoxDecoration(
color: Color(0xFF707070),
borderRadius: BorderRadius.all(
Radius.circular(
10.0,
),
)),
child: Flexible(
child: ListView.builder(
controller: _scrollController,
itemCount: prd.length + 1,
itemExtent: 42.5,
itemBuilder: (context, i) {
if (i == prd.length) {
return CupertinoActivityIndicator();
}
return ListTile(
title: AutoSizeText(prd[i]),
);
}),
),
);
}
I am working on a to do list app on flutter and I will like to sort the uploaded tasks by date(new ones appear first). for doing this I think a key should be givin to each of the uploaded items in the to do list and this key should include a Date. In react native for doing this I added a function to the data in a flatlist which sorted by date but since I am new to flutter I dont know how can that be done. Any Idea helps :)
main.dart
List<String> _toDoItems = []; //this is the array in which the uploaded tasks are stored, btw Im not using any database.
TextEditingController _controller = TextEditingController();
void _addToDoItem(String task) {
if(task.length > 0) {
setState(() {
_toDoItems.add(task);
});
}
}
void _removeTodoItem(int index) {
setState(() => _toDoItems.removeAt(index));
}
Widget _buildToDoItem(String toDoText, int index) {
return SizedBox(
child: Container(
height: 58,
margin: EdgeInsets.only(left: 22.0, right: 22.0, bottom: 12,),
decoration: BoxDecoration(
border: Border.all(width: 1.5, color: Colors.red),
borderRadius: BorderRadius.all(Radius.circular(18)),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children:[
Expanded(
child: ListTile(
title: Text(
toDoText,
style: TextStyle(fontSize: 18),
),
onTap: () => _removeTodoItem(index),
),
),
FlatButton(
child: Text('Delete', style: TextStyle(color: Colors.red, fontSize: 16.5),),
onPressed: () => _removeTodoItem(index),
),
],
),
),
);
}
Widget _buildToDoList() {
return Expanded(
child: ListView.builder(
itemBuilder: (context, index) {
if (index < _toDoItems.length) {
return _buildToDoItem(_toDoItems[index], index);
}
},
),
);
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(50),
child: AppBar(
centerTitle: true,
backgroundColor: Colors.red,
title: Text('To Do List', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold,),),
)
),
backgroundColor: Colors.white,
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 60,
margin: EdgeInsets.all(22),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 10,
child: Container(
height: double.infinity,
child: TextField(
controller: _controller,
autofocus: true,
onSubmitted: (val) {
_addToDoItem(val);
_controller.clear();
},
style: TextStyle(fontSize: 18,),
),
),
),
Expanded(
flex: 4,
child: Container(
height: double.infinity,
margin: EdgeInsets.only(left: 12),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('ADD', style: TextStyle(fontSize: 18)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
onPressed: () {
_addToDoItem(_controller.text);
_controller.clear();
FocusScope.of(context).requestFocus(FocusNode());
},
),
),
),
],
),
),
_buildToDoList()
]
),
),
);
}
You need to use the sort() method of List, also you need to be able to stock in a way or another the time of creation of your task.
I've made an example with the code you've posted. Using it your last created element will always be the first of the list.
import 'package:flutter/material.dart';
class ToDoElement {
final String task;
final DateTime timeOfCreation;
ToDoElement(this.task, this.timeOfCreation);
}
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
createState() => _MyAppState();
}
class _MyAppState extends State {
TextEditingController _controller = TextEditingController();
List<ToDoElement> _toDoItems = [];
void _removeTodoItem(int index) {
setState(() => _toDoItems.removeAt(index));
}
void _addToDoItem(String task) {
if (task.isNotEmpty) {
setState(() => _toDoItems.add(ToDoElement(task, DateTime.now())));
}
}
Widget _buildToDoItem(String toDoText, int index) {
return SizedBox(
child: Container(
height: 58,
margin: EdgeInsets.only(left: 22, right: 22, bottom: 12),
decoration: BoxDecoration(
border: Border.all(width: 1.5, color: Colors.red),
borderRadius: BorderRadius.all(Radius.circular(18)),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: ListTile(
title: Text(
toDoText,
style: TextStyle(fontSize: 18),
),
onTap: () => _removeTodoItem(index),
),
),
FlatButton(
child: Text(
'Delete',
style: TextStyle(color: Colors.red, fontSize: 16.5),
),
onPressed: () => _removeTodoItem(index),
),
],
),
),
);
}
int compareElement(ToDoElement a, ToDoElement b) =>
a.timeOfCreation.isAfter(b.timeOfCreation) ? -1 : 1;
Widget _buildToDoList() {
_toDoItems.sort(compareElement);
return Expanded(
child: ListView.builder(
itemCount: _toDoItems.length,
itemBuilder: (context, index) {
return _buildToDoItem(_toDoItems[index].task, index);
},
),
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(50),
child: AppBar(
centerTitle: true,
backgroundColor: Colors.red,
title: Text(
'To Do List',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
)),
backgroundColor: Colors.white,
body: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
Container(
height: 60,
margin: EdgeInsets.all(22),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 10,
child: Container(
height: double.infinity,
child: TextField(
controller: _controller,
autofocus: true,
onSubmitted: (val) {
_addToDoItem(val);
_controller.clear();
},
style: TextStyle(
fontSize: 18,
),
),
),
),
Expanded(
flex: 4,
child: Container(
height: double.infinity,
margin: EdgeInsets.only(left: 12),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('ADD', style: TextStyle(fontSize: 18)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
onPressed: () {
_addToDoItem(_controller.text);
_controller.clear();
FocusScope.of(context).requestFocus(FocusNode());
},
),
),
),
],
),
),
_buildToDoList()
]),
),
);
}
}
How to bottom align button in the popup ?
here is my tried code, but its giving some space from bottom.
I have used listview to build up popup
onPressed: () {
// Navigator.of(context).pushNamed(homePageTag);
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Form(
key: _formKey,
child: ListView(
shrinkWrap: true,//This tells items to be put in center
children: <Widget>[
FlatButton(
//padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
color: appGreenColor,
child: Text("UPDATE", style: TextStyle(color: Colors.white)),
onPressed: () {
},
),
],
),
),
);
});
},
Looking for this- https://ibb.co/19k2ty7
& getting this - https://ibb.co/h7KwXbn
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
Color myColor = Color(0xff00bfa5);
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: "Rounde Alert Box",
home: Scaffold(
appBar: AppBar(
backgroundColor: myColor,
title: Text("Rounded Alert Box"),
),
body: RoundedAlertBox(),
),
);
}
}
class RoundedAlertBox extends StatefulWidget {
#override
_RoundedAlertBoxState createState() => _RoundedAlertBoxState();
}
class _RoundedAlertBoxState extends State<RoundedAlertBox> {
#override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
onPressed: openAlertBox,
color: myColor,
child: Text(
"Open Alert Box",
style: TextStyle(color: Colors.white),
),
),
);
}
openAlertBox() {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(32.0))),
contentPadding: EdgeInsets.only(top: 10.0),
content: Container(
width: 300.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
"Rate",
style: TextStyle(fontSize: 24.0),
),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(
Icons.star_border,
color: myColor,
size: 30.0,
),
Icon(
Icons.star_border,
color: myColor,
size: 30.0,
),
Icon(
Icons.star_border,
color: myColor,
size: 30.0,
),
Icon(
Icons.star_border,
color: myColor,
size: 30.0,
),
Icon(
Icons.star_border,
color: myColor,
size: 30.0,
),
],
),
],
),
SizedBox(
height: 5.0,
),
Divider(
color: Colors.grey,
height: 4.0,
),
Padding(
padding: EdgeInsets.only(left: 30.0, right: 30.0),
child: TextField(
decoration: InputDecoration(
hintText: "Add Review",
border: InputBorder.none,
),
maxLines: 8,
),
),
InkWell(
child: Container(
padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
decoration: BoxDecoration(
color: myColor,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(32.0),
bottomRight: Radius.circular(32.0)),
),
child: Text(
"Rate Product",
style: TextStyle(color: Colors.white),
textAlign: TextAlign.center,
),
),
),
],
),
),
);
});
}
}