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

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

Related

Bottom Overflowed in Chrome / Desktop Resolution in Flutter

when i add container / listview in mobile resolution there is no bottom overflowed problem. (and the content can still be scrolled).enter image description here
however when i add container in chrome/desktop resolution
enter image description here
I've been looking for ways to solve this problem on the internet, such as adding
Expanded()
or
resizeToAvoidBottomPadding: false
and so on.
but still can't solve this problem.
here's my code:
`
import 'package:flutter/material.dart';
class MyDesktopBody extends StatelessWidget {
const MyDesktopBody({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black54,
appBar: AppBar(
title: const Text('D E S K T O P'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
// First Column
Expanded(
child: Column(
children: [
// Youtube Video
Padding(
padding: const EdgeInsets.all(8.0),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
height: 250,
color: Colors.redAccent,
),
),
),
// Comment Section & Recommended Videos
Expanded(
flex: 8,
child: ListView.builder(
shrinkWrap: true,
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.black54,
height: 120,
),
);
}),
)
],
),
),
// Second Column
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 200,
color: Colors.black54,
),
)
],
),
),
);
}
}
`
change the first Column into a Listview and remove the second Expanded and it should work properly
import 'package:flutter/material.dart';
class MyDesktopBody extends StatelessWidget {
const MyDesktopBody({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black54,
appBar: AppBar(
title: const Text('D E S K T O P'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
// First Column
Expanded(
child: ListView( //<---- here
children: [
// Youtube Video
Padding(
padding: const EdgeInsets.all(8.0),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
height: 20,
color: Colors.redAccent,
),
),
),
// Comment Section & Recommended Videos
ListView.builder( //<--here
shrinkWrap: true,
itemCount: 8,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.black54,
height: 120,
),
);
})
],
),
),
// Second Column
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 200,
color: Colors.black54,
),
)
],
),
),
);
}
}

Flutter add bottom margin to Stack

I am trying to extend Stack a little bit down to create room for "All caught up" text.
Here is my code;
return Stack(
children: [
buildListView(scrollController),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
Widget buildBackToTop(ScrollController scrollController, bool backtoTop) {
if (backtoTop) {
return Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FloatingActionButton.extended(
onPressed: () {
scrollController.animateTo(0,
duration: const Duration(milliseconds: 200),
curve: Curves.linear);
},
label: const Text("Back to Top"),
),
),
);
} else {
return const SizedBox();
}
}
Widget buildBottomReached(bool isLastIndex) {
if (isLastIndex) {
return const Align(
alignment: Alignment.bottomCenter,
child: Text(
"All caught up 🎉",
style: TextStyle(
color: Colors.blue, fontWeight: FontWeight.bold, fontSize: 20.00),
),
);
} else {
return const SizedBox();
}
}
Widget buildListView(ScrollController scrollController) {
return ListView.builder(
controller: scrollController,
itemCount: 50,
itemBuilder: (context, index) {
return SizedBox(
width: 20,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 20,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[100],
),
child: Center(
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Index $index"),
),
),
),
),
),
);
},
physics: const BouncingScrollPhysics());
}
When I do following,
return Stack(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 30),
child: buildListView(scrollController),
),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
This is desired but it adds whitespace to bottom all the time,
Is there a way to do this?
another valid solution for your case is to expand the Stack to the screen size, then align your widgets with the Align widget like this:
final mq = MediaQuery.of(context);
return ConstrainedBox(
constraints: BoxConstraints(
maxHeight: mq.size.height,
minHeight: mq.size.height,
maxWidth: mq.size.width,
minWidth: mq.size.width,
),
child: Stack(
fit: StackFit.expand,
children: [
buildListView(scrollController),
Align(
alignment: Alignment.bottomCenter,
child: buildBackToTop(scrollController, backtoTop),
),
buildBottomReached(isLastIndex),
],
),
);
Based on your UI. try Column widget instead of Stack.
return Column(
children: [
Expaneded(child: buildListView(scrollController)),
buildBackToTop(scrollController, backtoTop),
buildBottomReached(isLastIndex),
],
);
If it needs overlay, use Stack by combining listView and Text with Column.
Wrap the widget with Positioned and add bottom.
return Stack(
children: [
.....
Positioned(
bottom: yourValue,
child:
First, wrap Stack with ListView widget
Then, move buildBottomReached helper as a sibling of the Stack widget
return ListView(//this
children: [
Stack(
children: [
buildListView(),
buildBackToTop(backtoTop),
//buildBottomReached(isLastIndex),//move this a sibling of the Stack
],
),
buildBottomReached(isLastIndex),//moved here
],
);
Then, on buildListView helper, set ListView.builder property shrinkWrap to true.
Widget buildListView(ScrollController scrollController) {
return ListView.builder(
shrinkWrap: true,//this
controller: scrollController,
itemCount: 50,
itemBuilder: (context, index) {
return SizedBox(
width: 20,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 20,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
color: Colors.grey[100],
),
child: Center(
child: Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Index $index"),
),
),
),
),
),
);
},
physics: const BouncingScrollPhysics());
}

is there a way to embed a SingleChildScrollView (Vertical) within another SingleChildScrollView(Horizontal) in Flutter

In my app there is a SingleChildScrollView(with scrollable direction as Horizontal) which has a N number of containers.
Is there a way to embed a the SingleChildScrollView(with scrollable direction as Horizontal) into a SingleChildScrollView (with scrollable direction as Vertical) in Flutter.
for example:
class HomeBody extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: sidePadding,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
HomeAppbar(),
addVerticalSpace(15),
Text(
'Welcome, Jack',
style: themeData.textTheme.headline1,
),
addVerticalSpace(15),
SearchField(
width: mediasize.width - 2 * screenHorizontalPadding,
height: mediasize.height,
),
addVerticalSpace(25),
//I want to add a SingleChildScrollView (Vertical Direction) from this point to
TitleMoreBar(barTitle: 'Trending'),
addVerticalSpace(15),
//the FullProductCardHorizontalList() has a SingleChildScrollView(Horizontal direction)
FullProductCardHorizontalList(),
addVerticalSpace(25),
TitleMoreBar(barTitle: 'Popular Brands'),
addVerticalSpace(25),
//the BrandCardList() has a SingleChildScrollView(Horizontal direction)
BrandCardList(),
// this where the SingleChildScrollView (Vertical) should end
],
),
),
),
);
}
Yes, you can do this like:
import 'package:flutter/material.dart';
class ScrollTraining extends StatefulWidget {
#override
_ScrollingTraining createState() => _ScrollingTraining();
}
class _ScrollingTraining extends State<ScrollTraining> {
double mWidth;
#override
Widget build(BuildContext context) {
mWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: mWidth,
height: 400,
color: Colors.indigo,
margin: EdgeInsets.symmetric(vertical: 8.0),
alignment: Alignment.center,
child: Text("Fixed Box"),
),
Container(
width: mWidth,
height: 200,
margin: EdgeInsets.symmetric(vertical: 8.0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: getChildren(),
),
),
),
Container(
width: mWidth,
height: 400,
color: Colors.brown,
margin: EdgeInsets.symmetric(vertical: 8.0),
alignment: Alignment.center,
child: Text("Fixed Box"),
),
Container(
width: mWidth,
height: 200,
margin: EdgeInsets.symmetric(vertical: 8.0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: getChildren(),
),
),
),
],
),
),
);
}
List<Widget> getChildren() {
List<Widget> output = List();
List<Color> colorList = [
Colors.redAccent,
Colors.deepOrange,
Colors.orangeAccent,
Colors.yellow,
Colors.lightGreenAccent,
Colors.green,
Colors.greenAccent,
Colors.blue,
Colors.purpleAccent,
Colors.pink,
];
for (int i = 0; i < 10; i++) {
output.add(Container(
width: 140,
height: 200,
color: colorList[i],
));
}
return output;
}
}
I hope it is useful for you.

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,
),
),
],
),
)
],
),
);
},
),
...

Flutter - Scrollable Container

I have an app that has a listview of images(places) then when tapped, returns a new page displaying certain details about the place. My concern is about the details page, my layout is I have an image on top, some text below it and an expanded list view. What I want is that I can scroll thru whole page. What I came up with is that only the expanded list view is scrollable.
Here is the code for the details page:
import 'package:flutter/material.dart';
import 'package:craglist/cragspot.dart';
class CragDetailsScreen extends StatelessWidget {
final CragLocation loc;
final _placeTitleStyle = const TextStyle(
fontSize: 40.0, fontWeight: FontWeight.bold, color: Colors.black);
CragDetailsScreen(this.loc);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Details"),
),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
height: 300.0,
decoration: new BoxDecoration(
image: new DecorationImage(
fit: BoxFit.cover,
image: new AssetImage(loc.placeImage),
),
),
),
new Padding(
padding: const EdgeInsets.all(8.0),
child: new Text(
loc.name,
style: _placeTitleStyle,
),
),
new Padding(
padding: const EdgeInsets.only(left: 8.0),
child: new Text(
loc.desc,
),
),
new Padding(
padding: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 0.0),
child: new Divider(
height: 15.0,
),
),
new Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: new Text(
"Crags",
style: _placeTitleStyle,
),
),
new Expanded(child: _buildCragList()),
],
),
);
}
Widget _buildCragList() {
return new ListView.builder(
itemCount: loc.crag.length,
itemBuilder: (context, i) {
return _buildRow(loc.crag[i]);
});
}
Widget _buildRow(Crag crag) {
List<Widget> widcrag = [];
crag.routes.forEach((f) {
widcrag.add(
new ListTile(
dense: true,
title: new Text(f.name),
trailing: new Text(f.grade),
),
);
});
return new ExpansionTile(
title: new Text(crag.name),
children: widcrag,
);
}
}
Also additional - Is it possible that when I scroll the image resizes? To give the expanded list view more space on the screen.
You could wrap everything in a ListView.builder then add a if-statement to determine wether it is working on the first widget. If it is at the first widget, it adds all your content that should be at the top. If not it adds the normal List Items where index is +1. Something like this:
new ListView.builder(
itemCount: loc.crag.length,
itemBuilder: (context, index) {
int i = index;
if (i == 0) {
return new Column(children: <Widget>[
new Container(
height: 300.0,
decoration: new BoxDecoration(
image: new DecorationImage(
fit: BoxFit.cover,
image: new AssetImage(loc.placeImage),
),
),
),
new Padding(
padding: const EdgeInsets.all(8.0),
child: new Text(
loc.name,
style: _placeTitleStyle,
),
),
new Padding(
padding: const EdgeInsets.only(left: 8.0),
child: new Text(
loc.desc,
),
),
new Padding(
padding: const EdgeInsets.fromLTRB(8.0, 8.0, 8.0, 0.0),
child: new Divider(
height: 15.0,
),
),
new Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0),
child: new Text(
"Crags",
style: _placeTitleStyle,
),
),
],);
} else {
_buildRow(loc.crag[i+1]);
}
}
)