GridView in SimpleDialog is not updating - flutter

I am trying to implement a search function in GridView, which is on SimpleDialog. When I perform a search, the GridView is not updating. But when I scroll through GridView, It updates.
Below is my code
Widget _showParentCategory() {
return SimpleDialog(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: TextField(
onChanged: (value) {
finalList = myProducts
.where((product) => product["name"]
.toString()
.toLowerCase()
.contains(value.toLowerCase()))
.toList();
setState(() {
finalList;
});
},
decoration: const InputDecoration(suffixIcon: Icon(Icons.close)),
),
),
const SizedBox(
height: 20,
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.7,
width: MediaQuery.of(context).size.width,
child: Container(
color: Colors.white,
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 5.0,
mainAxisSpacing: 5.0),
itemCount: finalList.length,
itemBuilder: (BuildContext context, index) {
return Column(
children: [
const CircleAvatar(
backgroundColor: Colors.red,
radius: 20.0,
),
Text(finalList[index]["name"])
],
);
},
),
),
)
],
);
}
I tried to print my finalist which is getting updated but it seems setState is not working.
How can I redraw/ refresh GridView?

Related

GridView grid delegate display grids the same on all devices

I used gridView.builder. To set the size of the grid, I use MediaQuery, but for some reason the gridView is displayed differently on different devices, using which parameter in gridDelegate: can I fix this?
my gridView code:
Widget buildCatalog(List<Product> product) => CustomScrollView(
controller: sController,
slivers: [
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
// mainAxisExtent: ,
maxCrossAxisExtent: 300,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.3),
crossAxisSpacing: 10,
mainAxisSpacing: 10),
delegate: SliverChildBuilderDelegate(childCount: product.length,
(BuildContext context, int index) {
return GestureDetector(
onTap: () {},
child: Container(
padding: const EdgeInsets.only(left: 2, right: 2, top: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8)),
child: Column(
children: <Widget>[
InkWell(
child: Container(
margin: const EdgeInsets.only(top: 5),
child: Image.network(),
),
),
const SizedBox(
height: 10,
),
Text(),
// Spacer(),
const SizedBox(height: 8),
Text(),
const SizedBox(height: 5),
buildButton(index, productItem.id),
],
),
),
);
}),
),
]
);
This is my grid on big displays:
and this on small displays:
The solution was flutter_screenutil package

Flutter how to show array data in gridview?

I have a simple gridview and static which is working fine now i need to show data from array. I need to know how can i do this. By for loop i think it will not good but i am not sure the other way ?
My code
Container(
color: Color(0xffECF0F1),
child: GridView(
padding: EdgeInsets.all(0),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 1,
mainAxisSpacing: 1,
crossAxisCount: 4,
),
children: <Widget>[
],
),
),
In children i have data like this now
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => BookService1()),
);
},
child: Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: Height * 0.04,
child: Image.asset('images/cat1.png'),
),
SizedBox(
height: Height * 0.008,
),
Text(
'Computer Hardware',
style: TextStyle(
fontFamily: 'UbuntuMedium',
fontSize: 10,
),
textAlign: TextAlign.center,
)
],
),
),
),
Now i need to show data from array not static my array look like this
[
{
"Name": "Computer Software",
"Image": "https://cdn.zeplin.io/5fa90ed1e66d311f086e0115/assets/75b908a5-60c0-4e9a-84a4-ae3ca65c6973.png"
},
{
"Name": "Computer Hardware",
"Image": "https://cdn.zeplin.io/5fa90ed1e66d311f086e0115/assets/75b908a5-60c0-4e9a-84a4-ae3ca65c6973.png"
}
]
You can use the GridView.builder widget
GridView.builder(
itemCount: myArray.length, // The length Of the array
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.6,
crossAxisSpacing: 4,
mainAxisSpacing: 4,
), // The size of the grid box
itemBuilder: (context, index) => Container(
child: Text(myArray[index].text),
),
);
I have edited your code so you can try like as this code.
GridView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
//scrollDirection: Axis.vertical,
itemCount:myArray.length, // Your array item length.
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 1,
mainAxisSpacing: 1,
crossAxisCount: 4,
),
itemBuilder: (context, index) {
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => BookService1()),
);
},
child: Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: Height * 0.04,
child: Image.asset('images/cat1.png'),
),
SizedBox(
height: Height * 0.008,
),
Text(
myArray[index].name, // You can use like as
style: TextStyle(
fontFamily: 'UbuntuMedium',
fontSize: 10,
),
textAlign: TextAlign.center,
)
],
),
),
);
}),
I hope you are understand, So please let me know it's working or not.
Both above answers are correct but for clean code or the better way you can create a widget in which you can your data and show. So the benefit will be you can call that widget again so you can save code and also better structure.
Widget category:
import 'package:flutter/material.dart';
class CategoryBox extends StatefulWidget {
const CategoryBox({Key key, #required this.data}) : super(key: key);
final data;
#override
_CategoryBoxState createState() => _CategoryBoxState();
}
class _CategoryBoxState extends State<CategoryBox> {
#override
Widget build(BuildContext context) {
print(widget.data);
double statusBarHeight = MediaQuery.of(context).padding.top;
double Height = MediaQuery.of(context).size.height;
double Width = MediaQuery.of(context).size.width;
return GestureDetector(
onTap: () {
},
child: Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: Height * 0.04,
child: Image.network(widget.data['Image']),
),
SizedBox(
height: Height * 0.008,
),
Text(
widget.data['Name'],
style: TextStyle(
fontFamily: 'UbuntuMedium',
fontSize: 10,
),
textAlign: TextAlign.center,
)
],
),
),
);
}
}
your grid code
Container(
color: Color(0xffECF0F1),
child: GridView.builder(
itemCount: globalService
.globalServiceArray.length, // The length Of the array
padding: EdgeInsets.all(0),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 1,
mainAxisSpacing: 1,
crossAxisCount: 4,
),
itemBuilder: (context, index) => Container(
child: CategoryBox(data: globalService.globalServiceArray[index]),
),
),
),
change your array I have just given name. Both above answer is correct also if you are using the widget multiple times so I think this way will be good. Happy Coding :)

Flutter: Scroll view not responding

I am pretty new to flutter. I have build a landing page using grid view and added a bottom navigation bar. The navigation bar is called first after login in and I have added the screen to the navigation class. The issue am facing is that the navigation bar is on top of my grid items, when I try to scroll up, the grid items are sticky and not moving, what am I not doing right??
my home screen code
class GridDashboard extends StatelessWidget {
var services = [
"Home",
"Update",
"Bluetooth",
"Forms",
"Supervisor",
"Messages",
"Settings",
"App updates",
"Logout",
];
var images = [
"assets/home.png",
"assets/updated.png",
"assets/bluetooth.png",
"assets/todo.png",
"assets/supervisor.png",
"assets/message.png",
"assets/setting.png",
"assets/update.ico",
"assets/logout.png",
];
#override
Widget build(BuildContext context) {
List<Items> myList = [home, update, bluetooth, forms, supervisor, messages, settings, check, logout];
var color = 0xff453658;
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 500,
// margin: EdgeInsets.only(top: 10),
// padding: EdgeInsets.all(20),
child: GridView.builder(
// add this
shrinkWrap: true,
itemCount: services.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.4),
),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
Navigator.push(context, new MaterialPageRoute<Widget>(
builder: (BuildContext context) {
if(myList != null){
return myList[index].screen;
}else{
return null;
}
}));
},
child: Padding(
padding: EdgeInsets.all(3),
child: Card(
elevation: 10,
child: ListView(
children: <Widget>[
SizedBox(
height: 20,
),
Image.asset(
images[index],
height: 50.0,
width: 50.0,
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(
services[index],
style: TextStyle(
fontSize: 16.0,
height: 1.2,
color: Colors.white,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
],
),
color: Color(color),
),
),
);
},
),
),
);
}
}
class Items {
String title;
String subtitle;
String event;
String img;
final Widget screen;
Items({this.title, this.subtitle, this.event, this.img, this.screen});
}
my Nav bar code
class _NavSCreenState extends State<NavSCreen> {
final List<Widget> _screens = [Home()];
final List<IconData> _icons = const [
Icons.home,
Icons.settings,
MdiIcons.accountCircleOutline,
MdiIcons.accountGroupOutline,
Icons.menu,
];
int _selectedIndex = 0;
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: _icons.length,
child: Scaffold(
body: IndexedStack(index: _selectedIndex, children: _screens),
bottomNavigationBar: Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: CustomTabBar(
icons: _icons,
selectedIndex: _selectedIndex,
onTap: (index) => setState(() => _selectedIndex = index),
),
),
));
}
}
Try this by adding SingleChildScrollView. Hope this will solve your problem.
#override
Widget build(BuildContext context) {
List<Items> myList = [home, update, bluetooth, forms, supervisor, messages, settings, check, logout];
var color = 0xff453658;
return Scaffold(
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 500,
// margin: EdgeInsets.only(top: 10),
// padding: EdgeInsets.all(20),
child: GridView.builder(
// add this
shrinkWrap: true,
itemCount: services.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.4),
),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
Navigator.push(context, new MaterialPageRoute<Widget>(
builder: (BuildContext context) {
if(myList != null){
return myList[index].screen;
}else{
return null;
}
}));
},
child: Padding(
padding: EdgeInsets.all(3),
child: Card(
elevation: 10,
child: ListView(
children: <Widget>[
SizedBox(
height: 20,
),
Image.asset(
images[index],
height: 50.0,
width: 50.0,
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Text(
services[index],
style: TextStyle(
fontSize: 16.0,
height: 1.2,
color: Colors.white,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
],
),
color: Color(color),
),
),
);
},
),
),
),
),
);
}
You need to embed the GridView into a SingleChildScrollView widget. This widget handles the scrolling for its child, which is in your case the GridView. The same applies to ListView.
See the links for detailed documentation.
// ...
child: Container(
height: 500,
child: SingleChildScrollView(
child: GridView.builder(
// ...
)
)
)
// ...
EDIT
I forgot, that you have to give a GridView a height to work inside a SingleChildScrollView. You can use a Container that wraps the GridView.
// ...
child: Container(
height: 500,
child: SingleChildScrollView(
child: Container(
height: 500,
child: GridView.builder(
// ...
)
)
)
)
// ...
But with that approach you have to give your GridView a predefined height. An alternative is the CustomScrollView but you have to use a SliverGrid for that.
CustomScrollView(
slivers: [
SliverGrid(
// ...
)
]
)

Flutter Page reloads when keyboard opens or closes

I am working on a chat page using flutter so the page structure is
Container(
color: color,
child: Column(
children: <Widget>[
Flexible(
child: ScrollablePositionedList.builder(
itemScrollController: _itemScrollController,
itemPositionsListener: _itemPositionListener,
initialScrollIndex: _messages.length - 1,
padding: EdgeInsets.all(8.0),
reverse: false,
itemBuilder: (_, int index) => GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
print("tapped");
FocusScope.of(context).requestFocus(new FocusNode());
},
child: ChatMessage(
message: _messages[index],
),
),
itemCount: _messages.length,
),
),
Divider(
height: 1.0,
),
Container(
padding: EdgeInsets.only(bottom: 32, left: 8, right: 8),
decoration: new BoxDecoration(
color: Theme.of(context).cardColor,
),
child: _textComposerWidget(),
)
],
),
);
The problem is when click on textFrom or when keyboard opens or closes the page reloaded and i loss every data in the listView and in the textForm()
Need more info, seems like you are using StatelessWidget instead of Stateful

Flutter Gridview or StaggeredGridview variable width /variable number of items to fill column

I am trying to display a gridview that has variable number and width buttons like this:
But what I have ended up with when trying gridview is a fixed number of buttons and fixed widths like this:
Initially I thought this was a problem with the buttons having too much padding by default but that is not the issue, I was able to fix that and still have the same issue with the grid.
I have tried Gridview builder like this:
GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 3.5, mainAxisSpacing: 4, crossAxisSpacing: 4),
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
//Navigator.of(context).pushNamed(HomePageResultsScreen.id);
},
child: ButtonTheme(
minWidth: 16,
height: 30,
child: RaisedButton(
padding: EdgeInsets.all(8.0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
color: Colors.white,
child:
Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
CachedNetworkImage(fit: BoxFit.contain,
height: 40,
width: 40,
placeholder: (context, url) => new CircularProgressIndicator(),
imageUrl: snapshot.data.documents[index]['icon'].toString(),
),
Text(snapshot.data.documents[index]['name'].toString(), textAlign: TextAlign.right, style: TextStyle(fontSize: 10, color: Colors.black,),),
],
),
),
onPressed: (){
},
),
),
);
},
itemCount: snapshot.data.documents.length,
);
I have also edited the attributes of the builder to haveSliverGridDelagateWithMaxCrossAxisExtent and other attributes. I know the buttons as they are if not placed inside the grid will shrink to minimum size but when in the grid they expand to fill up the whole column.
I have also tried numerous ways by replacing the gridview with a staggered gridview like this:
StaggeredGridView.countBuilder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
crossAxisCount: 3,
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(2, index.isEven ? 2 : 1),
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
//Navigator.of(context).pushNamed(HomePageResultsScreen.id);
},
child: ButtonTheme(
minWidth: 16,
height: 30,
child: RaisedButton(
padding: EdgeInsets.all(8.0),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
color: Colors.white,
child:
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
CachedNetworkImage(fit: BoxFit.contain,
height: 20,
width: 20,
placeholder: (context, url) => new CircularProgressIndicator(),
imageUrl: snapshot.data.documents[index]['icon'].toString(),
),
Text(snapshot.data.documents[index]['name'].toString(), textAlign: TextAlign.center, style: TextStyle(fontSize: 10, color: Colors.black,),),
],
),
onPressed: (){
},
),
),
);
},
itemCount: snapshot.data.documents.length,
),
I have tried both StaggeredGridView.countBuilder and StaggeredGridView.extent but both of these are even further from what I imagined. It just ends up with a single button per gridview row (looks like a listview).
I am not sure what I am doing wrong or if this is even possible with these widgets.
Thanks for your help
you have to use StaggeredGridView and you have to find logic to calculate an item width and set StaggeredTile.count.
final List<String> testing = ['Baby Foods', 'Confectionery', 'Coffee', 'Packets & Units','Packets & Units unis', 'Processed Cheese', 'Factional Care', 'Sauce', 'Sauc'];
Container(
width: width,
child: StaggeredGridView.countBuilder(
itemCount: resting.length,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
crossAxisCount: 8,
staggeredTileBuilder: (int index) {
if (testing[index].length < 5) {
return StaggeredTile.count(2, 1);
} else if (testing[index].length < 16) {
return StaggeredTile.count(3, 1);
} else {
return StaggeredTile.count(4, 1);
}
},
mainAxisSpacing: 12.0,
crossAxisSpacing: 10.0,
itemBuilder: (BuildContext context, int index) {
return TextButton(
child: Text(testing[index]),
onPressed: () {},
);
},
),
),
# # Staggered View
# ScreenShot
![alt text](https://github.com/Anup2712/flutterAnup/blob/master/StaggeredView/Screenshot.jpg)
# What is it?
A Flutter staggered grid view which supports multiple columns with rows of varying sizes.
It’s a grid layout where the cross axis is divided in multiple equally sized parts, and places elements in optimal position based on available main axis space.
You’ve probably came across some app or website design with staggered grid layout like Pinterest:
# For understand the code
To help you to understand the code, you can see that this grid of 10 tiles is divided into 4 columns:
![alt text](https://github.com/Anup2712/flutterAnup/blob/master/StaggeredView/understanding.png)
# Let's Get Started
<H3>1 - Depend on it</h3>
<h6><b>Add it to your package's pubspec.yaml file</b></h6>
<pre>dependencies:
fl_chart: ^0.6.1</pre>
<H3>2 - Install it</h3>
<h6><b>Install packages from the command line</b></h6>
<pre>flutter packages get</pre>
<H3>2 - Getting Started</h3>
<h6><b>Import the package:</b></h6>
<pre>import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';</pre>
<pre>import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:ofsdp/pages/home.dart';
import 'package:ofsdp/util/appdrawer.dart';
class AdministrativeUvit extends StatefulWidget {
#override
_AdministrativeUvitState createState() => _AdministrativeUvitState();
}
class _AdministrativeUvitState extends State<AdministrativeUvit> {
var _scaffoldkey = GlobalKey<ScaffoldState>();
List<StaggeredTile> _staggeredTiles = const <StaggeredTile>[
const StaggeredTile.count(1, 1),
const StaggeredTile.count(1, 1),
const StaggeredTile.count(1, 1),
const StaggeredTile.count(1, 1),
const StaggeredTile.count(1, 1.5),
const StaggeredTile.count(1, 1.5),
];
List<Widget> _tiles = const <Widget>[
const _Example01Tile(Colors.green, Icons.widgets),
const _Example01Tile(Colors.lightBlue, Icons.wifi),
const _Example01Tile(Colors.amber, Icons.panorama_wide_angle),
const _Example01Tile(Colors.brown, Icons.map),
const _Example01Tile(Colors.deepOrange, Icons.send),
const _Example01Tile(Colors.indigo, Icons.airline_seat_flat),
const _Example01Tile(Colors.red, Icons.bluetooth),
const _Example01Tile(Colors.pink, Icons.battery_alert),
const _Example01Tile(Colors.purple, Icons.desktop_windows),
const _Example01Tile(Colors.blue, Icons.radio),
];
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Image.asset(
"assets/images/footer.jpg",
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
),
Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
backgroundColor: Color.fromRGBO(117, 80, 0, 1),
title: const Text("ADMINISTRATIVE UNIT"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.home),
onPressed: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => HomePage(),
),
);
},
)
],
),
drawer: AppDrawer(),
key: _scaffoldkey,
body: new Padding(
padding: const EdgeInsets.only(top: 12.0),
child: new StaggeredGridView.count(
crossAxisCount: 2,
staggeredTiles: _staggeredTiles,
children: _tiles,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
padding: const EdgeInsets.all(4.0),
)))
],
);
}
}
class _Example01Tile extends StatelessWidget {
const _Example01Tile(this.backgroundColor, this.iconData);
final Color backgroundColor;
final IconData iconData;
#override
Widget build(BuildContext context) {
return new Card(
color: backgroundColor,
child: new InkWell(
onTap: () {},
child: new Center(
child: new Padding(
padding: const EdgeInsets.all(4.0),
child: new Icon(
iconData,
color: Colors.white,
),
),
),
),
);
}
}</pre>
If these containers are not buttons (mean you don't need to click on each of them to do specific something) then you can use Wrap Widget
https://www.youtube.com/watch?v=z5iw2SeFx2M
https://medium.com/flutter-community/flutter-wrap-widget-e1ee0b005b16