How to use Expanded with Future - flutter

Part of my code is as follows:
Expanded(
flex: 13,
child: Container(
padding: EdgeInsets.all(2),
color: Colors.black12,
child: FutureBuilder(
future: getCompromissos(),
builder: (context, snapshot) {
if (compromissosFiltrados != null && compromissosFiltrados.compromissos.length > 0) {
return ListView.builder(
controller: ScrollController(),
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: compromissosFiltrados.compromissos.length,
itemBuilder: (context, index) {
return CompromissoCard(
indice: index,
title: compromissosFiltrados.compromissos[index].nome,
icon: new Icon(icons[0], size: 24.0, color: Colors.green));
},
);
} else {
return Container();
}
},
),
),
),
Sometimes getCompromissos() does not return any item and I have that empty space in my app.
I would like Expanded occupied all the space when there are nothing to show, like this:
In the lower part Expanded( flex: 0 is working because contents of that widget don't come from the web.
But in this widget if I use flex : 0 and there's not item, it's ok, but if there are items then I have errors like this:
RenderBox was not laid out: RenderRepaintBoundary#6c79b
relayoutBoundary=up6 NEEDS-PAINT
'package:flutter/src/rendering/box.dart': Failed assertion: line 1694
pos 12: 'hasSize'
In case you need that part of CompromissoCard
return new Container(
color: Colors.white12,
child: new Card(
child: Container(
color: Colors.white30,
padding: new EdgeInsets.only(left: 5, top: 5, bottom: 5, right: 10),
child: new Row(children: <Widget>[
Column(children: <Widget>[
SizedBox(height: 15),
Column(children: <Widget>[new Image.asset("assets/images/meeting.png")])
]),
Column(children: <Widget>[
Row(
children: <Widget>[
Column(children: <Widget>[
SizedBox(
height: 15,
),
Text("13:00 - 14:00", style: TextStyle(color: Colors.black38, fontSize: 16)),
SizedBox(
height: 5,
),
Text(this.title, style: TextStyle(color: Colors.black, fontSize: 16, fontWeight: FontWeight.w300))
]),
],
),
])
]),
),
));
I can't figure out how to do this.
Someone could help me? Thanks in an advance.

Related

Flutter: Make all screen scrollable with GridView.builder inside

In my home screen my app shows carousel first then a vertical list of challenges cards retrieved from Cloud Firestore using GridView.builder as follows:
GridView.builder(
scrollDirection: Axis.vertical,
itemCount: _challenges.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 4),
),
itemBuilder: (context, index) {
return InkWell(
onTap: () {
if (_challenges[index]["isLocked"] == "true") {
showLockedDialog();
} else {
checkParticipation(index);
if (checkPart == true) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
ChallengeDetails(_challenges[index])));
}
checkPart = true;
}
},
child: Stack(
children: [
Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image(
image: NetworkImage(_challenges[index]["image-path"]),
fit: BoxFit.cover,
height: 150,
width: 350,
opacity: _challenges[index]["isLocked"] == "true"
? AlwaysStoppedAnimation(.4)
: null,
),
),
),
Center(
child: Text(
"${_challenges[index]["name"]}\n",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
Center(
child: Text(
"\n${_challenges[index]["date"]}",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
textDirection: TextDirection.ltr,
)),
Center(
child: SizedBox(
height: 130,
width: 130,
child: _challenges[index]["isLocked"] == "true"
? Image.asset("assets/lock-icon.jpg")
: null,
),
)
],
),
);
});
Everything retrieving fine and it is rendered in my home_screen as follows:
body: Column(
children: [
AdsBanner(),
SizedBox(
height: 30,
),
Padding(
padding: const EdgeInsets.only(right: 8, left: 8, bottom: 5),
child: Row(
children: [
Text(
AppLocalizations.of(context)!.challenges + " ",
style: TextStyle(fontSize: 20),
),
Text(
AppLocalizations.of(context)!.clickToParticipate,
style: TextStyle(fontSize: 15),
)
],
),
),
Expanded(child: ChallengeCard()),
],
),
The problem is that only the GridView area is scrolling and what am seeking for is to scroll the whole screen with the GridView area, I was trying to use the CustomScrollView() but its not working properly.
I'll be thankful for any help.
First in your GridView.builder add these:
GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
...
)
then in your home_screen wrap your column with SingleChildScrollView:
SingleChildScrollView(
child: Column(
children: [
AdsBanner(),
SizedBox(
height: 30,
),
Padding(
...
),
),
You can provide physics: NeverScrollableScrollPhysics() on GridView to disable scroll effect. If you want scrollable as secondary widget use primary: false, to have Full Page scrollable, you can use body:SingleChildScrollView(..) or better using body:CustomScrollView(..)

Flutter - ListView nested in columns gives error "hasSize"

I have a ListView.builder() nested inside multiple columns, I get the following error and the widget doesn't build at all due to this:
════════ Exception caught by rendering library
═════════════════════════════════ RenderBox was not laid out:
RenderShrinkWrappingViewport#813d4 relayoutBoundary=up40 NEEDS-PAINT
NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
package:flutter/…/rendering/box.dart:1 Failed assertion: line 1982 pos
12: 'hasSize'
The relevant error-causing widget was ListView
lib\…\Widgets\todolistmodule_briefcard.dart:81
Below is the code:
class TodolistModuleBriefCard extends StatelessWidget {
//const NotesBriefModule({ Key? key }) : super(key: key);
TodolistModule todolistModule;
TodolistModuleBriefCard({required this.todolistModule});
#override
Widget build(BuildContext context) {
return buildCard();
}
Widget buildCard() => Padding(
padding: EdgeInsets.symmetric(vertical: 5),
child: Container(
child: Card(
color: Color.fromARGB(255, 240, 240, 240),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
child: buildContent(),
),
),
);
Widget buildContent() => Column(
children: [
buildName(),
Divider(
height: 1,
),
buildTodoList()
],
);
Widget buildName() => Padding(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15),
child: Text(
todolistModule.name,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontFamily: AppConfig.primaryFontFamily,
fontSize: 17,
color: Colors.grey.shade700,
fontWeight: FontWeight.w500,
),
),
);
Widget buildTodoList() => Padding(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
buildTodoListSubList(
subList: todolistModule.todo, subListTitle: "To Do"),
buildTodoListSubList(
subList: todolistModule.completed, subListTitle: "Complete")
],
),
);
Widget buildTodoListSubList(
{required List<String> subList, required String subListTitle}) =>
Column(
children: [
buildTodoListSubListTitle(title: subListTitle),
buildTodoListSubListItems(subList: subList),
],
);
Widget buildTodoListSubListTitle({required String title}) => Text(
title,
style: TextStyle(fontFamily: AppConfig.primaryFontFamily),
);
Widget buildTodoListSubListItems({required List<String> subList}) =>
ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: subList.length,
itemBuilder: ((context, index) {
return buildTodoListSubListItem(item: subList[index]);
}),
);
Widget buildTodoListSubListItem({required String item}) => Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Text(item,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
maxLines: 3,
style: TextStyle(
fontFamily: AppConfig.primaryFontFamily, fontSize: 13)),
),
);
}
Could someone please help me solve this problem?
just add Expanded
Widget buildTodoList() => Padding(
padding: EdgeInsets.symmetric(vertical: 5, horizontal: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: buildTodoListSubList(
subList: todolistModule.todo, subListTitle: "To Do"),
),
Expanded(
child: buildTodoListSubList(
subList: todolistModule.completed, subListTitle: "Complete"),
)
],
),
);
But you need read more about the layout principle
there is two solution:
you can surround your ListView with a container with a certain height like a height of your screen from media query for example:
Column(children: [
Container(
width: double.infinity,
height: 400,
child: ListView.builder(
itemBuilder: (context, index) {
return Container(
width: 200,
height: 890,
color: Colors.red,
child: Text('Hello'),
);
},
itemCount: 1,
),
)
]),
the second solution but I think it will stop the scrollable but try it is to set shrinkWrap property in listView to true like this:
Column(children: [
ListView.builder(
shrinkWrap: true, // this is shrinkWrap property!!!
itemBuilder: (context, index) {
return Container(
width: 200,
height: 400,
color: Colors.red,
child: Text('Hello'),
);
},
itemCount: 1,
)
]),

Extra "Space" In ListView and Card Flutter

I'm having this "extra space" on my first listview item that is a card being encapsulated in a container.
How do I remove it?
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(15.0),
height: 300,
child: Column(children: [
Row(children: [
Expanded(
child: Text("Lowest Fuel Price",
style: TextStyle(
fontWeight: FontWeight.w500,
color: Theme.orange3,
fontSize: 16.0)))
]),
Container(
height: 250,
child: Card(
elevation: 3,
child: ListView.builder(
itemCount: cheapest.length,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
final item = cheapest[index];
return Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text(
item.petrolType,
style: TextStyle(
color: Theme.gray1, fontSize: 18),
),
Text(
"\$" + item.petrolPrice,
style: TextStyle(
color: Theme.gray1, fontSize: 25),
),
Image(
fit: BoxFit.fill,
image: new AssetImage(
'assets/images/fuel_station/' +
item.petrolStation.toLowerCase() +
'.png')),
]),
index != cheapest.length - 1
? Divider(
color: Colors.grey,
)
: Divider(color: Colors.white)
],
);
})),
)
]));
}
https://api.flutter.dev/flutter/widgets/ListView-class.html
By default, ListView will automatically pad the list's scrollable extremities to avoid partial obstructions indicated by MediaQuery's padding. To avoid this behaviour, override with a zero-padding property.
Card(
elevation: 3,
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: ListView.builder(),
),
),

Why can't I scroll page?

I have a widget ListView but still I can't scroll through the pictures. I tried replacing Column but still it didn't work for me. Is there any other option?
Also, when I wrap StreamBuilder with SingleChildScrollView I get following error:
RenderBox was not laid out: RenderRepaintBoundary#9fda5 relayoutBoundary=up11 NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1702 pos 12: 'hasSize'
Here is my code:
StreamBuilder(
stream: Firestore.instance
.collection('userImage')
// .orderBy('date', descending: true)
.where('name', isEqualTo: name)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
return ListView(
children: [
Row(
children: [
Text('$name'),
IconButton(
icon: Icon(
Icons.open_in_new,
size: 30,
color: Colors.grey,
),
onPressed: logout)
],
),
Row(
children: [
Image.asset(
'assets/like.png',
height: 30,
width: 30,
),
Image.asset(
'assets/donate.png',
height: 30,
width: 30,
),
Icon(
Icons.offline_bolt,
color: Colors.grey,
size: 36,
),
],
),
Padding(
padding: const EdgeInsets.only(
left: 100, right: 100, top: 50, bottom: 50),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
child: SizedBox(
height: 50,
child: Center(
child: Text(
'order pics & clips',
style: TextStyle(color: Colors.white),
)),
),
onPressed: () {
print(name);
print(email);
print(account);
},
),
),
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, i) {
return Column(
children: [
ProfilePost(
snapshot.data.documents[i]['url'],
snapshot.data.documents[i]['likes'].toString(),
snapshot.data.documents[i]['donations']
.toString())
],
);
}),
],
);
}),
You could use the shrinkWrap: true property on the ListView() and ListView.builder() widgets so that the total size (height) of the listview is the sum of the heights of the children.

How to display ListView inside a Container without setting Container height in Flutter?

In my Flutter project, I show a list of data using ListView which is wrapped with Container. Now, when I am using the Container without setting it's height it shows the following error-
RenderBox was not laid out: RenderRepaintBoundary#a418c
relayoutBoundary=up16 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart': Failed assertion: line 1687
pos 12: 'hasSize'
And here's the entire structure of the class I have written-
SingleChildScrollView(
child: Column(
children: <Widget>[
showTheHistory(),
Container(
height: MediaQuery.of(context).size.height-ScreenUtil.instance.setWidth(260),
child: Padding(
padding: EdgeInsets.only(left: ScreenUtil.instance.setWidth(10), right: ScreenUtil.instance.setWidth(10)),
child: Container(
color: Colors.white,
child: FutureBuilder<List>(
future: _searchList,
initialData: List(),
builder: (context, snapshot) {
return snapshot.hasData ?
new ListView.builder(
padding: EdgeInsets.all(ScreenUtil.instance.setWidth(10)),
itemCount: snapshot.data.length,
itemBuilder: (context, i) {
return _buildRow(snapshot.data[i]);
},
)
: Center(
child: NoResultFoundScreen(),
);
},
),
),
),
),
SizedBox(height: ScreenUtil.instance.setHeight(10),),
Container(
width: MediaQuery.of(context).size.width,
child: Padding(
padding: EdgeInsets.only(left: ScreenUtil.instance.setWidth(10), right: ScreenUtil.instance.setWidth(10) ),
child: Column(
children: <Widget>[
Card(
elevation: 6,
child: Padding(
padding: EdgeInsets.all(ScreenUtil.instance.setWidth(5)),
child: Row(
children: <Widget>[
Text('English to ${Credentials.languageType}', style: TextStyle(fontSize: ScreenUtil.instance.setSp(18), color: Colors.teal, fontWeight: FontWeight.bold),)
],
),
),
),
Padding(
padding: EdgeInsets.only(top:ScreenUtil.instance.setWidth(10)),
child: Card(
color: Colors.white,
elevation: 10,
child: Container(
child: Column(
children: <Widget>[
getHowToUseText('1. '),
Padding(
padding: const EdgeInsets.only(left:8.0, right: 8.0),
child: Divider(height: 2, color: Colors.grey,),
),
getHowToUseText('2. While typing you will get auto suggestions. You can tap on the words to see meaning'),
],
),
),
),
)
],
),
),
),
SizedBox(
height: ScreenUtil.instance.setHeight(160),
)
],
),
),
So, as you can see that these is a height set to the Container wrapping the ListView. In the ListView, the data takes time to load and in that period of time the Container with that fixed size remains blank which is visibly not good. So, I need a solution to make that Listview height dynamic in spite of setting the height of the Container.
add shrinkWrap: true property to the listview also remove the container .
Also you have so many redundant widgets. You should consider refactoring your codes. You should have a look at the widgets docs on flutter.dev