I'm attempting to create a scrollable listview inside of a container which also contains a static image. However, the listview doesn't appear to be scrollable and I get a "bottom overflow by x pixels" artifact on my app.
static List<Widget> getClubs() {
var myClubs = new List<Widget>();
for (var i = 0; i < 10; i++) {
myClubs.add(new Padding(
padding: EdgeInsets.all(8.0),
child: new CircleAvatar(
backgroundImage:
new NetworkImage("https://i.imgur.com/p2oUDLD.png"),
backgroundColor: Colors.black,
radius: 34.0,
)));
}
return myClubs;
}
final leftSection = new Container(
color: Color(0xFF212121),
width: 100,
child: Column(
children: <Widget>[
SizedBox(height: 20.0),
new Image.asset(
'assets/logo.png',
alignment: Alignment.center,
),
SizedBox(height: 10.0),
new Container(
child: new ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(5.0),
children: getClubs(),
))
],
));
You can use Expanded widget or set the height for the Container.
I would also recommend Wrap for anyone running into an issue where a container is sized wrong within the listview, causing an overflow:
new Container(
alignment: Alignment.center,
child: Wrap( //the magic
children: [
new Container(),
],
),
),
Sometimes best way to fix an estimated height is using sizedbox
int heightToBeReduced = 380;
SizedBox(
height: MediaQuery.of(context).size.height - heightToBeReduced,
child: ListView....
)
wrap the Column in an Expanded widget:
Expanded(
child: Column(
),
),
Another way is to wrap the Column in a Flexible widget and specify a flex factor.
Flexible(
flex: 1,
child: Column(
children: [
],
),
),
I used a Flexible in a Row to control the output of the listview builder
Define the scollController
final _scrollController = ScrollController();
Define the ListView builder
ListView builder = ListView.builder(
itemCount: listPerformance?.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return PerformanceCardWidget(performanceView: listPerformance[index]);
});
Define a flexible that outputs the listview builder contents
Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Flexible(
flex: 6,
fit: FlexFit.loose,
child: Scrollbar(
isAlwaysShown: true,
controller: _scrollController,
child: SingleChildScrollView(
controller: _scrollController, child: builder))
)
])
Related
I am trying to use ListView.builder to display a horizontal list in a Stack but am encountering this weird bug when scrolling ListView if I set itemCount: 10. If I set itemCount: 20 the ListView scrolls like normal.
I have tested in the emulator (Galaxy Nexus 720x1280 android 5.0) and on a real device (Nokia 7 plus, android 9.0). How can I fix this?
class BugPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: <Widget>[
Positioned(
left: 20.0,
right: 20.0,
height: 60.0,
bottom: 70.0,
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10, // Overflow when scroll.
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 3.0,
),
child: Container(
width: 40.0,
height: 40.0,
color: Colors.red,
child: Center(child: Text("$index")),
),
);
},
),
),
SizedBox(width: 10.0),
FloatingActionButton(
backgroundColor: Colors.blue,
onPressed: () {},
child: new Icon(
Icons.add,
color: Colors.black,
),
),
],
),
),
],
),
),
);
}
}
Expected output:
Actual output:
And a video of the problem
I tried your code and run with bigger intemcount too without problems, but i have an advice, change the
SizedBox(width: 10.0)
for a padding around the button
Padding(
padding: const EdgeInsets.only(left: 10),
child: FloatingActionButton(
backgroundColor: Colors.blue,
onPressed: () {},
child: new Icon(
Icons.add,
color: Colors.black,
),
)
)
It seems like this bug appears in old flutter version after I updated to newest version everything is ok.
I have used ClipRRect for rounded corners in the UI. The ClipRRect wraps topContent and bottomContent are a stack and a Column respectively. But, the bottom corners are not round. What may be the reason behind this?
The cardModel class is used to store the image path in this case.
class FeaturedCard extends StatelessWidget {
final FeaturedCardModel cardModel;
final double parallaxPercent;
FeaturedCard({
this.cardModel,
this.parallaxPercent = 0.0, //default value
});
#override
Widget build(BuildContext context) {
final topContent = Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(
left: 10.0,
),
height: MediaQuery.of(context).size.height * 0.3,
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage(cardModel.imgUrl),
fit: BoxFit.fill,
),
)),
],
);
final bottomContentText = Text(
'This is the sample text',
style: TextStyle(fontSize: 18.0),
);
final bottomContent = Container(
height: MediaQuery.of(context).size.height * 0.5,
width: MediaQuery.of(context).size.width,
color: Colors.white,
padding: EdgeInsets.all(40.0),
child: Center(
child:
bottomContentText,
),
);
return ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Column(
children: <Widget>[
topContent,
bottomContent,
],
),
);
}
}
If you go to Flutter Inspector and do "Toggle Debug Paint" you will see that the clipping occurs in the blue area below.
You can fix it by giving a size to your clipper.
return SizedBox(
height: MediaQuery.of(context).size.height * 0.8,
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Column(
children: <Widget>[
topContent,
//bottomContent,
],
),
),
);
The column that is the child of ClipRRect is taking as much space as it can get. so the border radius is applied to the bottom of the screen.
to solve that you just need to set mainAxisSize property of Column to MainAxisSize.min:
return ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
topContent,
bottomContent,
],
),
);
I'm trying to build a layout where there are two Text objects at the top and bottom which stays stationery and a ListView at their center.
Here's the code for the Screen
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(vertical: 40.0),
child: Text(
DateFormat("hh:mm 'PM ,' MMMM d").format(DateTime.now()),
style: Theme.of(context).textTheme.title,
),
),
Expanded(
child: ListView.builder(
itemCount: 4,
itemBuilder: (BuildContext context, int index) =>
CustomAppText(
text: 'Custom App',
),
),
),
Container(
margin: EdgeInsets.symmetric(vertical: 40.0),
child: Text(
"Settings",
style: Theme.of(context).textTheme.title,
),
),
],
),
),
),
);
}
}
The output of the given code
The Design I'm looking for
I have tried using the Center widget but it does not center the ListView
The ListView fills the entire Expanded Widget, that's why using the Center widget didn't work, so shrinkWrap: true should be added so the ListView takes only the height of it's children.
After skimming through the documentation I found about Flexible Widget
Flexible, which does not force the child to fill the available space.
Made the change and works like a charm
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemCount: 4,
itemBuilder: (BuildContext context, int index) =>
CustomAppText(
text: 'Custom App',
),
),
),
For those still looking for an answer, this is what worked for me:
Column(
children: [
Container(), // some top content
Expanded(
child: Center(
child: ListView(
shrinkWrap: true,
children: [] //your list view content here
)
)
),
Container(), // some bottom content
]
)
The Expanded widget makes the content take up all available space.
The Center widget centers the content you want to display.
The ListView holds your list content and the "shrinkWrap: true" property makes your list view shrink according to content size(allowing it to centralized by the Center widget when it's not taking a lot of space).
Hope it helps. Give the top and bottom widgets the 25% of the screen size. Give the listview the 50% of the screen size.
import 'package:flutter/material.dart';
class TestPage extends StatefulWidget {
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
#override
Widget build(BuildContext context) {
final _size = MediaQuery.of(context).size;
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(28.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// Top Widgets
Container(
width: double.infinity,
// color: Colors.green,
height: _size.height * 0.25, // Take 25% width of the screen height
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('11: 25 AM', style: TextStyle(fontSize: 23.0),),
Text('Set As Launcher', style: TextStyle(fontSize: 23.0),)
],
),
),
Expanded(
child: Container(
// color: Colors.yellow,
child: ListView(
children: List.generate(25, (index){
return Text('Custom App $index', style: TextStyle(fontSize: 45.0),);
}),
),
),
),
// Bottom Widgets
Container(
width: double.infinity,
// color: Colors.blue,
height: _size.height * 0.25, // Take 25% width of the screen height
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Settings', style: TextStyle(fontSize: 23.0),),
],
),
)
],
),
),
),
);
}
}
Just add an Expanded as a wrapper for your first Container inside the Column
Expanded(
child: Container(
margin: EdgeInsets.symmetric(vertical: 40.0),
child: Text(
DateFormat("hh:mm 'PM ,' MMMM d").format(DateTime.now()),
style: Theme.of(context).textTheme.title,
),
),
),
Just wrap your ListView.builder inside a container class and give it a height, either explicitly in double or as a percentage of screen height.
class Trial extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
margin: EdgeInsets.symmetric(vertical: 40.0),
child: Text(
"Some Text",
style: Theme.of(context).textTheme.title,
),
),
Container(
// height: 40,
height: MediaQuery.of(context).size.height * 0.4,
child: ListView.builder(
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return Text("Hello");
}
),
),
Container(
margin: EdgeInsets.symmetric(vertical: 40.0),
child: Text(
"Settings",
style: Theme.of(context).textTheme.title,
),
),
],
),
),
),
);
}
}
Add two spacer it will give you 100% same result as you expected
Spacer(),
Expanded(
child: ListView.builder(
itemCount: 4,
itemBuilder: (BuildContext context, int index) =>
CustomAppText(
text: 'Custom App',
),
),
),
Spacer(),
It have to use shrinkWrap: true and Flexible together to show
all items of ListView.
Flexible(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: models.length,
If you replace your Expanded widget with a Container and give that a fixed height, I think you get what you are looking for.
How to solve the scrolling issue in flutter layout when adding gridview inside listview. in android studio java we use NestedScrollView to solve this type of issue What is the solution for flutter?
I need to scrolling continues with out any problem with listview with custom view and gridview.Now then gridview is only allowing to scroll gridview if i scroll grid view then top imageview is not scrolling .How to solve this issue?
body:
ListView(
children: <Widget>[
new Image.network("https://www.gizbot.com/img/2013/11/23-weekend-deals-top-10-latest-smartphones.jpg"),
Container(
height: 300.0,
child: GridView.count(
crossAxisCount: 3,
childAspectRatio: .6,
children: _list.map((p) => ProductManagment(p)).toList(),
),
)
],
)
After adding #deniss answer
SOLVED
Instead of use ListView you should use Column Widget Like below.
body:
Column(
children: <Widget>[
Container (
height: 150.0, // Set as you want
child: Image.network("https://www.gizbot.com/img/2013/11/23-weekend-deals-top-10-latest-smartphones.jpg")),
Container(
height: 300.0,
child: GridView.count(
crossAxisCount: 3,
childAspectRatio: .6,
children: _list.map((p) => ProductManagment(p)).toList(),
),
)
],
)
Because of `GridView` itself has scroll effect.
EDITED:
Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
child: ListView(
children: <Widget>[
Column(
children: <Widget>[
Container(
height: 200,
child: Image.network(
"https://www.gizbot.com/img/2013/11/23-weekend-deals-top-10-latest-smartphones.jpg"),
),
ConstrainedBox(
constraints: BoxConstraints(
minHeight: 80, // Set as you want or you can remove it also.
maxHeight: double.infinity,
),
child: Container(
child: GridView.count(
crossAxisCount: 3,
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: NeverScrollableScrollPhysics(),
childAspectRatio: .6,
children: _list.map((p) => ProductManagment(p)).toList(),
),
),
)
],
),
],
),
));
You have to use ConstrainedBox with set maxHeight: double.infinity and GridView.count set shrinkWrap: true,. and remove container height 300.
Also if you want to change
Container(
height: 200,
child: Image.network(
"https://www.gizbot.com/img/2013/11/23-weekend-deals-top-10-latest-smartphones.jpg"),
),
To Just
Image.network("https://www.gizbot.com/img/2013/11/23-weekend-deals-top-10-latest-smartphones.jpg")
Than you can change it.
I had the same issue. However, I did not want the issue of Overflowed by... that comes with a Column/Row and instead added physics: ScrollPhysics() to my GridView.count to resolve this issue. Found my answer from this response to a similar issue.
use this
child: GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 2.0,
mainAxisSpacing: 2.0,
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: NeverScrollableScrollPhysics(),
children: List.generate(choices.length, (index) {
return Center(
child: new Column(
children: [
new Expanded(
child: SelectCard(choice: choices[index]),
),
],
),
);
}),
));
and full code for better explanation
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
var url = "https://miro.medium.com/max/2160/1*9JzKFil-Xsip742fdxDqZw.jpeg";
class Dashboard extends StatefulWidget {
_Dashboard createState() => _Dashboard();
}
Widget _buildAvatar(BuildContext context, Orientation orientation) {
return Container(
height: 300.0,
color: Colors.blue,
child: Center(
child: CircleAvatar(
backgroundColor: Colors.white,
child: Text('RR'),
),
),
);
}
Widget _buildFields(BuildContext context) {
return Container(
color: Colors.white,
child: GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 2.0,
mainAxisSpacing: 2.0,
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: NeverScrollableScrollPhysics(),
children: List.generate(choices.length, (index) {
return Center(
child: new Column(
children: [
new Expanded(
child: SelectCard(choice: choices[index]),
),
],
),
);
}),
));
}
class _Dashboard extends State<Dashboard> {
#override
Widget build(BuildContext context) {
return OrientationBuilder(builder: (context, orientation) {
return ListView(
children: <Widget>[
Container(
height: 200,
child: Image.network(
"https://www.gizbot.com/img/2013/11/23-weekend-deals-top-10-latest-smartphones.jpg"),
),
_buildFields(context),
],
);
});
}
}
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
const List<Choice> choices = const <Choice>[
const Choice(title: 'Home', icon: Icons.home),
const Choice(title: 'Contact', icon: Icons.contacts),
const Choice(title: 'Map', icon: Icons.map),
const Choice(title: 'Phone', icon: Icons.phone),
const Choice(title: 'Camera', icon: Icons.camera_alt),
const Choice(title: 'Setting', icon: Icons.settings),
const Choice(title: 'Album', icon: Icons.photo_album),
const Choice(title: 'WiFi', icon: Icons.wifi),
];
class SelectCard extends StatelessWidget {
const SelectCard({Key key, this.choice}) : super(key: key);
final Choice choice;
#override
Widget build(BuildContext context) {
final TextStyle textStyle = Theme.of(context).textTheme.display1;
return Container(
child: GridView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 1,
childAspectRatio: 1,
),
itemBuilder: (contxt, indx) {
return Card(
elevation: 4,
margin: EdgeInsets.all(8),
color: Colors.white70,
child: Padding(
padding: const EdgeInsets.only(top: 25),
child: Container(
width: 4,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new Expanded(
child: new Container(
child: new Icon(
choice.icon,
color: Colors.black,
size: 50.0,
),
),
flex: 2,
),
new Expanded(
child: new Container(
margin: EdgeInsets.only(top: 12),
child: new Text(
choice.title,
style:
TextStyle(fontSize: 16, color: Colors.black),
)),
flex: 1,
),
]),
),
),
);
},
),
);
}
}
Does any one know how to accomplish the shrinking of the child view in Flutter as show here in the first picture. I used a gridView which does the job very well.
On the second picture I used a row, I tried it with Container and Constrains but it didn't worked out very well. ;D
return new GridView.count(
crossAxisCount: 3,
padding: const EdgeInsets.all(16.0),
mainAxisSpacing: 4.0,
shrinkWrap: true,
crossAxisSpacing: 4.0,
children: widget.foodItems.map((FoodViewModel food){
return new FoodTile(
name: food.name,
icon: food.icon
, onPressed: (bool state) {
food.isSelected = state;
widget?.onFoodItemTaped(food, state);
},
);
}).toList(),
);
Here the row-code without any constrains
return new SingleChildScrollView(
child: new Container(
margin: const EdgeInsets.all(16.0),
child:new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Container(
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name: "Tile one", onPressed:(bool state){}),
),
new Container(
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name: "Tile two", onPressed:(bool state){}),
),
new Container(
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name: "Tile three", onPressed:(bool state){}),
)
],
)
));
Complete source code to the tile
You should wrap the instances of FoodTile in a Flexible or Expanded so that the Row will apply a flexible layout model to them and space them evenly.
Just if someone is wondering how the end result looks. I'm still a bit unhappy with the "LayoutBuilder-Solution" but it works for me right know.
return new SingleChildScrollView(
child: new Container(
margin: const EdgeInsets.all(16.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Expanded(child: new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints){
return new Container(
constraints: new BoxConstraints.tightFor(width: constraints.maxWidth, height: constraints.maxWidth),
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name:"hallo",onPressed: (bool state){}),
);
})),
new Expanded(child: new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints){
return new Container(
constraints: new BoxConstraints.tightFor(width: constraints.maxWidth, height: constraints.maxWidth),
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name:"hallo 2",onPressed: (bool state){}),
);
})),
new Expanded(child: new LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints){
return new Container(
constraints: new BoxConstraints.tightFor(width: constraints.maxWidth, height: constraints.maxWidth),
padding: const EdgeInsets.all(2.0),
child: new FoodTile(name:"hallo 3",onPressed: (bool state){}),
);
})),
],
),