I cannot seem to get my screen to scroll. I have tried a few variations of the following code but I have not been able to get it to work. I also tried it with a ListView that did not work very well either. Admittedly, I did not try to troubleshoot the ListView for very long because I was assuming the issue was being caused by something else. I have looked on SO and seen a few questions about this topic and they helped me fix some issues, but I cannot seem to get it to work. I do not get any error messages or anything, my screen simply does not scroll. Below you will see the general layout of my code. What am I doing wrong?
class _TripPackagesState extends State<TripPackages> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(...),
GestureDetector(...),
],
),
),
),
Container(
margin: EdgeInsets.only(top: 1.0),
child: SingleChildScrollView(
child: StreamBuilder<QuerySnapshot>(
stream:
Firestore.instance.collection('trip_package').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> docSnapshot) {
if (!docSnapshot.hasData) return const Text('Loading...');
final int docCount = docSnapshot.data.documents.length;
return GridView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: docCount,
itemBuilder: (_, int index) {
DocumentSnapshot document =
docSnapshot.data.documents[index];
return GestureDetector(
child: Container(
margin: EdgeInsets.all(3.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(...),
Row(...),
],
),
),
);
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(...),
);
},
),
),
),
],
),
);
}
}
Try using primary: false in your GridView.builder
Related
Good day.
I am trying to build a UI where the widget tree is like Row -> children(Column, List). The problem is I want my column to take the same height as the List. It is not happening. I am including screenshots and my code here. Any kind of help is appreciable
You can see that the column on the left is not taking all the space and space between the time and expanding more icons is not working either.
I am including my code here.
class CollapsibleAgendaList extends StatelessWidget {
#override
Widget build(BuildContext context) {
final SessionListCubit cubit = context.read<SessionListCubit>();
return ListView.separated(
itemBuilder: (context, index) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: GestureDetector(
onTap: () {
print('Tapped on time section. ');
},
child: Padding(
padding: EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('10:30 Am'),
Icon(Icons.expand_more),
],
),
),
),
),
Expanded(
child: ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
print("item builder.");
return CollapsibleAgendaItem(
session: cubit.state.sessions[index], isLiked: true);
},
separatorBuilder: (context, index) {
return const Divider(
color: Colors.grey,
);
},
itemCount: 2),
),
],
);
},
separatorBuilder: (context, index) {
return const Divider(
color: Colors.grey,
);
},
itemCount: 4);
}
}
Edit: I'm going to explain the reason for this problem in my case. Maybe it will help someone in the future. When Flutter builds the child it asks for the required width/height from the parent. But as I used a ListView as a child, it doesn't know the height instantly. So, the Column was taking only the height it needed. But, I experimented that providing a height for the ListView solve the problem. But, In my case, I can't determine the height in runtime, instead, I used a Column like the accepted answer, which solved my problem. In the future, If someone finds a solution with ListView, Please do comment here.
You can top Row with IntrinsicHeight(expensive-widget). Also while you are not using scrollable physics, you can replace listVIew with Column
return ListView.separated(
itemBuilder: (context, index) {
return IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ColoredBox(
color: Colors.red,
child: GestureDetector(
onTap: () {
print('Tapped on time section. ');
},
child: Padding(
padding: EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('10:30 Am'),
Icon(Icons.expand_more),
],
),
),
),
),
Column(
children: List.generate(2, (index) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 200,
),
const Divider(
color: Colors.grey,
),
],
);
}),
),
],
),
);
},
separatorBuilder: (context, index) {
return const Divider(
color: Colors.grey,
);
},
itemCount: 4);
Use mainAxisSize:MainAxisSize.max inside column.
To make the contents of the Row fill the entire height, you need to set crossAxisAlignment: CrossAxisAlignment.stretch, on the Row.
Here is the documentation on CrossAxisAlignment vs MainAxisAlignment.
CrossAxisAlignment.stretch
Stretches children across the cross axis. (Top-to-bottom for Row, left-to-right for Column)
In my application I am listing in an appBar several Containers that have the names of product categories, these categories are being listed in the body with their respective products.
The ListView that is in the appBar has the same indexes of the ListView of the body, so the idea was to press the index 'x' in the appBar and the user would be redirected to the index 'x' in the body.
I tried many solutions, one of then was the package https://pub.dev/packages/scrollable_positioned_list, but it did not works because when calling the function to scroll my list just disappears.
Here's de code:
return Scaffold(
backgroundColor: Colors.white,
appBar: PreferredSize(
preferredSize: Size.fromHeight(120),
child: Column(
children: [
AppBar(...),
Expanded(
child: Container(
color: AppColors.primary,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: widget.listaProdutos.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.symmetric(...),
child: GestureDetector(
child: Container(
decoration: BoxDecoration(...),
child: Padding(...),
child: Center(
child: Text(
widget.listaProdutos[index].dsGrupo,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
onTap: () {
SHOULD SCROLL TO INDEX
},
),
);
},
)
),
),
],
),
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: widget.listaProdutos.length,
itemBuilder: (context, indexGrupo) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(...),
ListView.builder(..),
],
);
},
),
),
],
),
),
);
You can use PageView with scrollDirection: Axis.vertical,
class TFW extends StatefulWidget {
const TFW({super.key});
#override
State<TFW> createState() => _TFWState();
}
class _TFWState extends State<TFW> {
final PageController controller = PageController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: PreferredSize(
preferredSize: Size.fromHeight(100),
child: Expanded(
child: ListView.builder(
itemCount: 100,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
controller.animateToPage(index,
duration: Duration(milliseconds: 400),
curve: Curves.easeIn);
},
child: SizedBox(width: 100, child: Text("$index")),
);
},
),
),
)),
body: PageView.builder(
controller: controller,
itemCount: 100,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Container(
color: index.isEven ? Colors.red : Colors.blue,
child: Text("$index"),
);
},
),
);
}
}
Fortunately I was able to resolve the problem. To help members who may have the same doubt I will register here the solution that worked for me. (sorry for the bad English)
Question: Why ScrollablePositionedList wasn't working? (as I mentioned iniatily)
Response: I was using the ScrollablePositionedList within a SingleChildScrollView, and for some reason when using the scrollTo or jumpTo function, the information that was visible simply disappeared. For that reason, I was trying to find a way to get success using a ListView (what came to nothing).
Solution: ... Trying to figure out why the ScrollablePositionedList wasn't working as it should ...
The initial structure was:
body: SingleChildScrollView(
child: Column(
children: [
Container(
child: ScrollablePositionedList.builder(
Changed for:
body: ScrollablePositionedList.builder(
The only reason for all this confusion is that ScrollablePositionedList's indexing functions for some reason don't work as they should if it's inside a SingleChildScrollView. So, take off SingleChildScrollView and all good.
I'm learning flutter to make an app. Here I'm trying to make a page to show the full post. The problem is that the page isn't scrolling as a single unit.
class SinglePostPage extends StatefulWidget {
final Post? post;
const SinglePostPage({Key? key, this.post}) : super(key: key);
#override
State<SinglePostPage> createState() => _SinglePostPageState();
}
class _SinglePostPageState extends State<SinglePostPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: const EdgeInsets.only(top: 22.5),
padding: const EdgeInsets.fromLTRB(0, 5, 0, 6),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BackButton(),
Row(
children: [
InkWell(
onTap: () {
showDialog(...);
},
child: CircleAvatar(...),
Container(
padding: const EdgeInsets.only(left: 5.4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () {
showDialog(...);
},
child: Text(
widget.post!.author[0].profileName,
),
),
const SizedBox(height: 4),
Text(
showTimeAgo(widget.post!.postTime).toString(),
),
],
),
),
],
),
PopupMenuButton(
icon: const Icon(Icons.more_vert),
itemBuilder: (context) => [...],
),
Container(
margin: const EdgeInsets.fromLTRB(12, 9, 12, 3),
// when the text is longer than the screen height it showed RenderFlex overflowed error so I put constraints. how to show it full and make this scroll
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.54,
minHeight: 50),
child: SingleChildScrollView(
child: Text(
widget.post!.postText,
textAlign: TextAlign.start,
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (widget.post!.postMedia.isNotEmpty)
CarouselSlider.builder(...),
const SizedBox(height: 4.5),
if (widget.post!.postMedia.length > 1)
buildDotIndicator(widget.post!.postMedia),
],
),
],
),
),
Container(
// post reactions row
),
CommentBodyWidget(
postId: widget.post!.postId,
),
],
),
);
}
}
I looked up for other answers and tried wrapping it with SingleChildScrollView, but it didn't work , and ListView with shrinkWrap: true also gave 'Incorrect use of ParentDataWidget' error.
CommentBodyWidget has a listview builder. It's scrolling on its own but the widget above isn't scrolling along with it.
How can I show this whole page and scroll together without having to limit the long post in a constrained container? Please help.
You can wrap body Column with SingleChildScrollView and use shrinkWrap: true, and use physics: NeverScrollableScrollPhysics(),. This will solve the issue.
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
//...
ListView.builder(
itemCount: itemlength,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return Text("item $index");
},
),
/// instead of listView
...List.generate(itemlength, (index) => Text("itemWidget"))
],
),
),
);
But I will encourage you to check CustomScrollView.
In order for the SingleChildScrollView to work, its parent's height should be defined.
You can achieve this by wrapping the SingleChildScrollView in a Container/SizedBox with defined height, or by wrapping it with the Expanded widget.
Pass SingleChildScrollView as body of your scaffold. Also shrinkwrap: true for the ListView is recommended so that it only takes up as much space as required, which will avoid unbounded height errors.
So instead of
...
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
...
Do this
...
Widget build(BuildContext context)
return Scaffold(
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(...
I recommend you to use CustomScrollView.
Try this:
CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column("""HERE PUT YOUR CODE""")
)]
),
Newbie here. I have managed to implement a ListView that simply displays images. However the ListView isn't scrollable. I have attempted to wrap it in SingleChildScrollView, have added physics to AlwaysScrollableScrollPhysics and also tried removing Expand widgets from the layout. What am I missing?
LAYOUT
return Scaffold(
body: SingleChildScrollView(
child: Column(children: [
SizedBox(
height: 6,
),
StreamBuilder(
stream: ref.onValue,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData &&
!snapshot.hasError &&
snapshot.data.snapshot.value != null) {
lists.clear();
DataSnapshot dataValues = snapshot.data.snapshot;
Map<dynamic, dynamic> values = dataValues.value as Map;
values.forEach((key, values) {
lists.add(values);
});
return new ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Card(
margin: EdgeInsets.fromLTRB(2, 2, 2, 2),
elevation: 20,
child: GestureDetector(
onTap: () {
String imageurl = lists[index]["image"];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FullScreenImageViewer(
imagurl: imageurl,
),
));
},
child: Padding(
padding: EdgeInsets.all(5),
child: Container(
width: 400,
child: Image(
image:
NetworkImage(lists[index]["image"]),
),
),
),
),
),
],
);
},
);
}
return Container();
},
),
]),
),
);
You can remove the single child scroll view, i believ the problem here is because you are using a column and the listview is not expanding to the whole screen. If you want to make sure the listview occupy the all the space remaining you can use the Flex and expanded widget.
Flex can work like a column or row depending on which direction you are providing it with. anything that is placed here behave exactly like when they is placed in the column or row except for Expanded, as they fill the remainning space.
I've changed your code a bit here to accomodate the Flex and Expanded widget (you just need to readd your logic and the streambuilder to make it work)
return Scaffold(
body: Flex(direction: Axis.vertical, children: [
const SizedBox(
height: 6,
),
Expanded(
// Change the children to stream builder if neccesary
child: ListView.builder(
shrinkWrap: true,
itemCount: 5,
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Card(
margin: const EdgeInsets.all(2),
elevation: 20,
child: GestureDetector(
onTap: () {
// ACTION HERE
},
child: const Padding(
padding: EdgeInsets.all(5),
child: Image(
image: NetworkImage("https://picsum.photos/200/300"),
),
),
),
),
],
);
},
),
)
]),
);
There's a property within listView() that tells it which irection the overflow is so as to scroll. Set it to
scrollDirection: Axis.horizontal
I am trying to learn how to create complex UI elements in flutter and faced this problem. Suppose I want to put a pageview in my listView and display the same items as in the horizontal scrolling list. Is there any way to do this?
Here is my code of build method with listview:
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _catList.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: [
Card(
child: ListTile(
title: Text(_catList[index].name),
),
),
IntrinsicWidth(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: Column (
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text ('ID: ${_catList[index].id}'),
Text ('Country code: ${_catList[index].countryCodes}'),
Text ('Temperament: ${_catList[index].temperament}'),
Text ('Origin: ${_catList[index].origin}')
],
)
),
Expanded(
child: Card(
child: Text(_catList[index].description),
),
)
],
),
),
Container (
child: PageView.builder (itemBuilder: (context, index) {
} ),
)
],
),
);
},
);
}
As i under stand you want to add PageView in side ListView. So your ListView scroll in vertical direction and your PageView scroll in horizontal direction. If i am not wrong then below is my code to do the same things.
I have made my List which contain multiple List like below.
var modelListOne = ["model_1_1.png", "model_1_2.png",];
var modelListTwo = ["model_2_1.png", "model_2_2.png",];
var modelList = [modelListOne, modelListTwo,];
return ListView.builder(
itemCount: modelList.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => YOURPAGE());
},
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
height: 350,
width: double.maxFinite,
child: PageView.builder(
itemCount: modelList[index].length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, pageIndex) {
return Container(
height: 300,
width: double.maxFinite,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"assets/images/${modelList[index][pageIndex]}",
),
fit: BoxFit.cover)),
);
}),
)),
),
);
});
Make changes regarding to your requirements. Thanks.