GridLayout Item Overflow flutter - flutter

I have a gridlayout with griditems being basically :
Cards
with two things :
Image
Text
But the image is being loaded through the internet hence sometimes it overflows the grid item box and this box does not change the height, what i want is the image should be of fixed size.
Here is my code : (How do i do it ? )
import 'package:flutter/material.dart';
import '../models/dbModel.dart';
class GridLayout extends StatelessWidget {
final List<DbModel> m;
var appContext;
GridLayout(this.m, this.appContext);
Widget build(context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, crossAxisSpacing: 7.0, mainAxisSpacing: 7.0),
padding: const EdgeInsets.all(10.0),
itemBuilder: (context, i) {
return GridItem(appContext, m[i]);
},
itemCount: m.length,
);
}
}
class GridItem extends StatelessWidget {
final appContext;
final dbModel;
GridItem(this.appContext, this.dbModel);
Widget build(context) {
return GestureDetector(
onTap: () {},
child: Card(
child: Column(
children: <Widget>[
dbModel.img == "NOLINK" ? Image.network("https://i.ibb.co/Vv6cPj4/404.png",) : Image.network(dbModel.img),
Container(
padding: EdgeInsets.all(10.0),
child: Text("${dbModel.title}"),
),
],
),
),
);
}
}

you need wrap image widget - Image.network with Expanded & add fit: BoxFit.cover,.
working code:
Widget build(context) {
return GestureDetector(
onTap: () {},
child: Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, //add this
children: <Widget>[
Expanded(
child: Image.network(
"https://i.ibb.co/Vv6cPj4/404.png",
fit: BoxFit.cover, // add this
),
),
Center(
child: Container(
padding: EdgeInsets.all(10.0),
child: Text("Title under"),
),
),
],
),
),
);
}
output:

Use Container and Inside a container declare the width and height of the image as
you want.
new Container(
width: 60.0
height: 60.0,
decoration: new BoxDecoration(
image: new DecorationImage(
image:Image.network("https://i.ibb.co/Vv6cPj4/404.png",),
//repeat: ImageRepeat.repeat,
),
),
)
I hope, this will help you.

Related

flutter gridview item at bottom

I have a gridView(3 items in a row) with dynamic number of items. I want gridView item should be at bottom means if there are 3 items then one row at bottom of screen, if there are 6 items then two row at bottom. So a dynamic padding at top depending on item count and screen size. My code structure is like below
class className extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
ImageFiltered(
//code here
),
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.black38,
),
GridView.builder(
primary: false,
reverse: false,
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 30,
),
itemBuilder: (context, index) {
return InkWell(
onTap: () {
//code
},
child: CustomWidget(
title: toolkitStore.getLabel(toolKit),
icon: ImageIcon(
AssetImage(
'assets/images/abcd.png'),
size: 48,
color: kWhiteColor,
),
),
);
},
itemCount: getCount().length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
),
],
),
),
);
}
}
Now I have this
but I want this
Thanks in advance.
**Try this one: **
import 'package:flutter/material.dart';
class ClassName extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Container(height: 100,width: 200,color: Colors.green,),//<----Your any widget
Align(
alignment: Alignment.bottomCenter,
child: GridView.builder(
primary: false,
reverse: true,
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 30,
),
itemBuilder: (context, index) {
return InkWell(
onTap: () {
//code
},
child: const Icon(Icons.person,size: 50,color: Colors.green,),
);
},
itemCount: 5,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
),
),
Container(height: 100,width: 100,color: Colors.red,),//<----Your any widget
],
),
),
);
}
}
Wrap your GridView.builder with Align widget provide alignment: Alignment.bottomCenter,
Align(
alignment: Alignment.bottomCenter,
child: GridView.builder(
primary: false,
reverse: false,
While using Stack use positional widget(Positioned, Align,...) to place children on UI.
Thank you, everyone.
I solved my problem by using Positioned widget and setting shrinkWrap: true, my code structure is
new Positioned(
left: 0.0,
bottom: 0.0,
width: MediaQuery.of(context).size.width,
child: GridView.builder(
shrinkWrap: true, //this is most important
))

Flutter ListView not scrolling (I feel like I've tried every solution on the internet)

If I drag and hold my finger down I can see a few items that are below the cutoff of the screen but as soon as I let go, it just bounces back to the top. I tried using SingleChildScrollView places, tried setting primary = true, and a bunch of other stuff that didn't help. I'm fairly new to flutter so any help would be appreciated!! Let me know if any more info is needed.
Here is my code:
import 'package:flutter/material.dart';
import 'package:drink_specials/models/restaurant.dart';
import 'package:drink_specials/screens/home/restaurant_list.dart';
class RestaurantNameTextStyle {
static TextStyle display5(BuildContext context) {
return Theme.of(context).textTheme.headline2.copyWith(color: Colors.white);
}
}
class RestaurantTypeTextStyle {
static TextStyle display5(BuildContext context) {
return Theme.of(context).textTheme.headline6.copyWith(color: Colors.white);
}
}
class RestaurantDetail extends StatelessWidget {
final Restaurant restaurant;
RestaurantDetail({Key key, #required this.restaurant}) : super(key: key);
#override
Widget build(BuildContext context) {
final topContentText = Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(height: 100.0),
Text(
restaurant.name,
style: RestaurantNameTextStyle.display5(context),
),
SizedBox(height: 10.0),
Expanded(
flex: 6,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(
restaurant.restaurant_type,
style: RestaurantTypeTextStyle.display5(context),
))),
],
);
final topContent = Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 10.0),
height: MediaQuery.of(context).size.height * 0.5,
decoration: new BoxDecoration(
image: new DecorationImage(
image: NetworkImage(restaurant.photo),
fit: BoxFit.cover,
),
)),
Container(
height: MediaQuery.of(context).size.height * 0.5,
padding: EdgeInsets.all(40.0),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(color: Color.fromRGBO(58, 66, 86, .9)),
child: Center(
child: topContentText,
),
),
Positioned(
left: 8.0,
top: 60.0,
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back, color: Colors.white),
),
)
],
);
final bottomContent = Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.all(8.0),
child: Center(
child: ListView.builder(
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
itemCount: restaurant.specials.length,
itemBuilder: (context, index) {
final item = restaurant.specials[index];
return Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(58, 66, 86, 1.0)),
child: ListTile(
contentPadding: EdgeInsets.symmetric(horizontal:20, vertical:10),
title: Text(item, style: TextStyle(color: Colors.white)),
)
),
);
}
),
),
);
return Scaffold(
body: Column(
children: <Widget>[
topContent,
Expanded(
child: bottomContent,
),
],
),
);
}
}
There is a ListView inside a SingleChildScrollView and both of them are scrollable. Scrolling on one of them should be disabled.
As they already explained. If you have a ListView.builder, you don't need SingleChildScrollView.
Try removing SingleChildScrollView. The code should look like this:
Scaffold(
body: Column(
children: <Widget>[
topContent,
Expanded(
child: bottomContent,
),
],
),
);
ListView already have scroll behavior so you won't need some SingleChildScrollView

Countdown in a ListView (Flutter)

I would like to find a solution to create countdowns from a date and put them in a ListView. I hope this does not slow down the application too much when using it.
I already have a code I want to keep, it's a RecyclerView with images and text.
Here's the code, if you need anything else I'll send it to you.
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import '../recyclerview/data.dart';
import 'package:watch/constants.dart';
class ListViewExample extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return new ListViewExampleState(
);
}
}
class ListViewExampleState extends State<ListViewExample>{
List<Container> _buildListItemsFromItems(){
int index = 0;
return item.map((item){
var container = Container(
decoration: index % 2 == 0?
new BoxDecoration(color: const Color(0xFFFFFFFF)):
new BoxDecoration(
color: const Color(0xFFFAFAF5)
),
child: new Row(
children: <Widget>[
new Container(
margin: new EdgeInsets.all(5.0),
child: new CachedNetworkImage(
imageUrl: item.imageURL,
width: 200.0,
height: 100.0,
fit: BoxFit.cover,
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 75.0 ),
child: Text(
item.title,
style: kItemTitle,
),
),
Container(
padding: const EdgeInsets.only(left: 15.0),
child:Text(
item.description,
style: kItemDescription,
),
),
]),
)
],
)
);
index = index + 1;
return container;
}).toList();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Accueil', style: kAppBarStyle,),
backgroundColor: Colors.white,
elevation: 0,
),
body: ListView(
children: _buildListItemsFromItems(),
),
);
}
}
Thank you!
Update : to add the countdown look this post :Date Countdown Timer
and for the lazy loading, I have changed my ListView to a ListView.builder
Is is suggested to use Listview.builder and not just put a list into ListView if you need lazy loading.
https://flutter.dev/docs/cookbook/lists/long-lists
Replace the ListView to ListView.builder.
ListView.builder(
itemCount: // items.length
itemBuilder: (buildContext, index) {}, // define what Widget for each index
)
Here is the sample code from yours. index is already exist in itemBuilder function.
...
body: ListView.builder(
itemCount: items.length,
itemBuilder: (buildContext, index) {
return Container(
decoration: index % 2 == 0
? new BoxDecoration(color: const Color(0xFFFFFFFF))
: new BoxDecoration(color: const Color(0xFFFAFAF5)),
child: new Row(
children: <Widget>[
new Container(
margin: new EdgeInsets.all(5.0),
child: new CachedNetworkImage(
imageUrl: item.imageURL,
width: 200.0,
height: 100.0,
fit: BoxFit.cover,
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.only(bottom: 75.0),
child: Text(
items[index].title,
),
),
Container(
padding: const EdgeInsets.only(left: 15.0),
child: Text(
items[index].description,
),
),
],
),
)
],
),
);
},
),
...

Items in ListView get it's height

I'm trying to create a horizontal list view with some card.
I want the list view to have height X and the cards to have height Y, I don't know why but the cards are getting the height of the list view.
This is what I have:
class FinanceApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: Container(
color: Color(0x180000),
child: Column(
children: <Widget>[
Header(),
SizedBox(
height: 20,
),
Expanded(
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(32.0),
topRight: Radius.circular(32.0),
),
),
child: Column(
children: <Widget>[
Container(
height: 250,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
CustomCard(),
CustomCard(),
],
),
),
],
),
),
),
],
),
),
),
);
}
}
EDIT: The only thing that kinda works for me, Is to wrap the card container in another container, use padding to get the size I want, but it does not seem like a great solution.
Check this out:
import 'package:flutter/material.dart';
class StackOverFlow extends StatefulWidget {
#override
_StackOverFlowState createState() => _StackOverFlowState();
}
class _StackOverFlowState extends State<StackOverFlow> {
#override
Widget build(BuildContext context) {
return Scaffold(
body:
Center(
child: Container(
color: Colors.blue,
height: 200.0,
width: double.infinity,
child: ListView.builder(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.all(16.0),
itemCount: 100,
itemBuilder: _buildItem,
),
),
),
);
}
Widget _buildItem (BuildContext context, int index) {
return Center(
child: Card(
child: Text(index.toString()),
),
);
}
}
And for giving children same size consider wrapping the cards with a Container:
Widget _buildItem (BuildContext context, int index) {
return Center(
child: Container(
height: 100.0,
width: 100.0,
child: Card(
child: Center(child: Text(index.toString())),
),
),
);
}

How to avoid other stack containers?

I have a chat widget that I've been having trouble with given the unique header. Finally figured out how to position the TextComposer at the base of the app and all looks great, however the ListView where the chat's occur overlaps the header after a certain number of text entries. I've been trying to figure out how to position the ListView.builder so that it stays below the header (_buildImage and _buildTopHeader) and doesn't overlap such as in the image below. Unfortunately I haven't been having any luck. Any suggestions would be greatly appreciated!
Thanks!
Header Overlap
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: Stack(children: <Widget>[
_buildIamge(),
_buildTopHeader(),
Container(
alignment: Alignment.center,
child: new ListView.builder(
padding: new EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
)),
]),
),
Container(
decoration:
new BoxDecoration(color: Theme.of(context).cardColor),
height: 50.0,
child: _buildTextComposer(),
alignment: Alignment.bottomCenter,
),
],
),
),
resizeToAvoidBottomPadding:false,
);
}
Stack renders its children list in order from top to bottom, with stuff on the bottom rendered over things at the top (it makes sense, I promise). So if you want the ListView to be rendered at the bottom of everything else, put it at the top of the children list:
Stack(
children: <Widget>[
Container(
alignment: Alignment.center,
child: new ListView.builder(
padding: new EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
),
),
_buildIamge(),
_buildTopHeader(),
],
),
Take a try with Positioned
Demo:
import 'package:flutter/material.dart';
class StackPositionPage extends StatefulWidget {
StackPositionPage({Key key, this.title}) : super(key: key);
final String title;
#override
_StackPositionPageState createState() => _StackPositionPageState();
}
class _StackPositionPageState extends State<StackPositionPage> {
var _headerHeight = 100.0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: buildBody(context),
);
}
Widget buildBody(BuildContext context) {
return SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: Stack(children: <Widget>[
_buildIamge(),
_buildTopHeader(),
Positioned(
top: _headerHeight,
left: 0,
right: 0,
bottom: 0,
child: ListView.builder(
padding: new EdgeInsets.all(8.0),
itemBuilder: (_, int index) => Padding(
padding: const EdgeInsets.all(16.0),
child: _buildMessage(index),
),
),
),
]),
),
Container(
color: Colors.blue,
height: 50.0,
alignment: Alignment.bottomCenter,
child: Center(
child: Text("Composer"),
),
),
],
),
);
}
Text _buildMessage(int index) => Text("Message " + (index + 1).toString());
Container _buildTopHeader() {
return Container(
height: _headerHeight,
color: Colors.pink,
child: Center(
child: Text("Header"),
),
);
}
Container _buildIamge() {
return Container(
color: Colors.grey,
);
}
}