I want to implement a horizontal scroll with categories:
I put my Categories section in Column (maybe it is not the right way, correct me please if I am wrong) and then I try to make my categories scrollable using ListView/Slivers. I have faced with issue that I need to specify constraints for ListView if I use it inside Column. I tried to wrap it with Expanded widget but it didnt work for me. Then I tried CustomScrollView and Slivers but it seems I am doing something wrong. Can you please suggest me the right structure of the widgtes for this view or correct me.
Container(
margin: EdgeInsets.all(40),
child: Column(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Category',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
Text(
'8 CATEGORIES',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
SizedBox(
height: 30,
),
CustomScrollView(
scrollDirection: Axis.horizontal,
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate([
CategoryCard(
title: 'Featured',
previewImageAsset:
'assets/images/bliny-shokolad-klubnika.jpg',
),
]),
)
],
),
Row(
children: <Widget>[
CategoryCard(
title: 'Featured',
previewImageAsset:
'assets/images/bliny-shokolad-klubnika.jpg',
),
],
),
],
),
),
],
),
),
You are getting the error when using the ListView the renderview port was exceeded. To fix this, warp your ListView in a Container widget and give it the height and width property:
Check below:
Container(
// change your height based on preference
height: 80,
width: double.infinity,
child: ListView(
// set the scroll direction to horizontal
scrollDirection: Axis.horizontal,
children: <Widget>[
// add your widgets here
CategoryCard(
title: 'Featured',
previewImageAsset:
'assets/images/bliny-shokolad-klubnika.jpg',
),
// space them using a sized box
SizedBox(width: 15,),
CategoryCard(
title: 'Featured',
previewImageAsset:
'assets/images/bliny-shokolad-klubnika.jpg',
),
],
),
),
Related
I'm trying to make a menu for a reastaurant like this one : -
I'm using Flutter and this is my code:
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: Row(
children: [
Expanded(child: Text( text, style: style, )),
const SizedBox( width: 15 ),
Text( '\$ $price', style: style,),
],
),
),
Divider( color: Colors.white.withOpacity( 0.5 ),),
],
);
But this is the result that I'm getting : -
Please, any help will be welcome.
And thanks in advance.
The result that you want to achieve can be done just by using the row widget, you don't have to wrap it up with ListTile. I am writing the code snippet of Row widget for you. You can copy paste it and it will work. Additionally I see that you are generating it in the column widget. If you have a dynamic array then I suggest that you use ListView Divider instead. It will have a divider to add between your rows as well. You can find more about it on flutter official documentation.
Row(
children:[
//You may add some padding to Text for better looking UI.
Text("Chicken Masala"),
Expanded(child:Divider()),
Text("180")
])
Just replace your column's children with this row and you will be able to see it.
I solved your issue like this:
Output of your issue : -
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: Row(
children: [
const Text(
'Cheese Burger',
),
Expanded(child: Text('.' * 100, maxLines: 1)),
const Text(
'\$ 10',
),
],
),
),
const SizedBox(
height: 10,
),
ListTile(
title: Row(
children: [
const Text(
'Chicken Masala Soup',
),
Expanded(child: Text('.' * 100, maxLines: 1)),
const Text(
'\$ 10',
),
],
),
),
],
),
#Ramji, #Dhruvil Patel, I try your code and it work fine, but it was making an overflow when the text was long, so I made some changes in your example and I got what I was looking for.
Thanks a lot for you help.
Here is what I dit.
return SizedBox(
width: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
Expanded( child: Text( text, style: style, maxLines: 2, overflow: TextOverflow.ellipsis, ) ),
],),
Row(
children: [
Expanded(
child: Text(
'.' * 150,
style: style,
maxLines: 1,
overflow: TextOverflow.fade,)),
SizedBox(
width: 80,
child: Text(
'\$ $price',
style: style,
textAlign: TextAlign.right,)),
],
),
// Divider( color: Colors.white.withOpacity( 0.5 ),),
],
),
);
here is the UI that I'm trying to build
but this is the output
I tried alignment also , but that also didn't working
but when setting a fixed height this is working fine
but I can't fill this using the fit parameter,
here is the code
Scaffold(
backgroundColor: kDarkTheme,
body: SafeArea(
child: Column(
children: [
const SizedBox(height: 10),
Row(
//code for top button
),
const SizedBox(height: 150),
Stack(
children: [
Center(
child: CircleAvatar(
radius: radiusSize + 5,
backgroundColor: kDarkCounterColor,
child: CircleAvatar(
backgroundColor: kDarkTheme,
radius: radiusSize,
),
),
),
Center(
child: Padding(
padding: const EdgeInsets.only(top: 35),
child: Text(
'39',
style: GoogleFonts.italiana(
fontSize: 120, color: kDarkCounterColor),
),
),
),
],
),
const SizedBox(height: 15),
const Text(
'Tap To Count',
style: TextStyle(
fontFamily: 'Helvatica',
color: Color(0xff656158),
),
),
Expanded(
child: Align(
alignment: Alignment.bottomRight,
child: SvgPicture.asset(
kDarkThemeImage,
)),
)
],
),
))
this is the code
then the first error appears again. how could I fix this?
You are using the Expanded widget on a column that doesn't have a set size. Try adding MainAxisSize attribute to your column, like this:
Column(
mainAxisSize: MainAxisSize.max, // Add this like
children: [
...
This will make your column fit the whole available size on the previous widget (a scaffold for the whole screen). Then the expanded widget will fill the remaining space not used by the other widgets inside the column.
I'm building a product detail page. As the following piece of code and image shown, when there is a lot of content in the description part, the bottom overflow will occur. I'm wondering how to make the page scrollable, I've tried wrapping the Stack with SingleChildScrollView, but this is definitely not working in my case here. Can anyone help me with that? Thank you very much!!!!!
class DetailsScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: [
buildBody("path/to/image", size),
],
),
);
}
Positioned buildBody(String imagePath, Size size) {
return Positioned.fill(
child: Column(
children: [
Expanded(
child: Container(
padding: EdgeInsets.symmetric(vertical: 60, horizontal: 30),
color: Colors.green,
child: Stack(
children: [
Align(
alignment: Alignment.center,
child: Hero(
tag: 1,
child: Image.asset(
imagePath,
width: size.width * 0.7,
),
),
),
],
),
),
),
Expanded(
child: Container(
color: Colors.white,
child: Column(
children: [
SizedBox(
height: 100,
),
Container(
margin: EdgeInsets.symmetric(
horizontal: 20,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(),
SizedBox(
width: 10,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Anvesha Shandilya',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16),
),
Text(
'Owner',
style: TextStyle(
color: fadedBlack,
),
),
],
),
Expanded(child: Container()),
Text(
'Dec 16, 2020',
style: TextStyle(
color: fadedBlack,
fontSize: 12,
),
),
],
),
),
SizedBox(
height: 30,
),
Container(
margin: EdgeInsets.symmetric(
horizontal: 20,
),
child: Text(
'A lot of content..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................',
style: TextStyle(
color: fadedBlack,
height: 1.7,
),
),
),
],
),
),
),
],
),
);
}
}
Error: Bottom Overflowed
To reproduce: Change the path/to/image, to this: A image can be used with the code:
tl;dr remove Expanded widgets -> remove Stack -> replace Column with ListView (for scrollability)
Start by removing Expanded widgets from the tree as you don't really need them. If possible, you should use mainAxisAlignment and crossAxisAlignment to position your widgets. That's exactly how you should handle placing the date next to user's name.
Expanded documentation states with which widgets you can use it:
Creates a widget that expands a child of a Row, Column, or Flex so
that the child fills the available space along the flex widget's main
axis.
Then remove Stack widget. If you don't then it will still work as Stack tries to get as big as its positioned children so it will just get as big as the Column you have inside. It's redundant.
Last but not least, replace Column with ListView. Column doesn't really care about whether it's overflowing or if it's being rendered. So if you create a Column that is bigger than the screen, it will simply display it which will cause the overflow. To fix that you could wrap it SingleChildScrollView, but I think it's more appropriate to just use ListView instead.
Here's an amazing explanation of layout system in Flutter: https://flutter.dev/docs/development/ui/layout/constraints
I'm getting the problem when I add Scrolling functionality in Scaffold, here I have tried SingleChildScrollView, CustomerScrollView, and ListView but it freezes the UI but when I replaced ti Scaffold to LayoutBuilder it works but all the background my UI got black.
I just want to add scrolling functionally to Scaffold.
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
...Some Code...
},
child: Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 3,
child: Container(
padding: EdgeInsets.all(15.0),
alignment: Alignment.bottomLeft,
child: Text(
mydata[0][i.toString()],
style: TextStyle(fontSize: 16.0, fontFamily: "Quando"),
),
)),
Expanded(
flex: 6,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
choiceButton('a'),
choiceButton('b'),
choiceButton('c'),
choiceButton('d'),
],
),
)),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.topCenter,
child: Text(showtimer,
style: TextStyle(
fontSize: 35.0,
fontFamily: "Times New Roman",
fontWeight: FontWeight.w700)),
))
],
),
) // Scaffold
);// WillPopScope
}
Try This
return Scaffold(
resizeToAvoidBottomInset: false,
extendBodyBehindAppBar: false,
backgroundColor: Colors.white,
body: Column(
children: <Widget>[
Expanded(
child: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
],
),
),
),
),
]
Don't use Expanded inside any scrolling container unless you wrap it in a fixed bound on its main axis.
Like in your case main axis is vertical and you are using expanded in it, since expanded needs a bound to limit its expansion, you should've remove that expanded thing or just wrap the container in a SizedBox for a specific height.
Than you can wrap the sized box in any scroll container which suits you.
Hope it helps!
In your code, change Column to ListView, and remove the expanded widget. you can use fixed height or MediaQuery.of(context).size.height * (any ratio) to the containers, or just don't specify any container height so it'll take its children's height.
here's the code will look like:
body: ListView(
shrinkWrap: true,
children: <Widget>[
Container(
// height: MediaQuery.of(context).size.height * (any ratio) / fixed height
child: Text(
mydata[0][i.toString()],
style: TextStyle(fontSize: 16.0, fontFamily: "Quando"),
),
),
Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
choiceButton('a'),
choiceButton('b'),
choiceButton('c'),
choiceButton('d'),
],
),
),
Container(
alignment: Alignment.topCenter,
child: Text(showtimer,
style: TextStyle(
fontSize: 35.0,
fontFamily: "Times New Roman",
fontWeight: FontWeight.w700)),
)
],
),
I used a card widget in my flutter App that has two rows, the problem that I have is a large space appeared between the two rows as you can see in the following image
how can fix this problem ?
my code that i tried it here :
return Card(
child: Container(
alignment: FractionalOffset.center,
child: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: ListTile(
title: Text(snapshot.data[index].data["title"],
textDirection: TextDirection.rtl,
style: TextStyle(fontSize: 14.0,
fontFamily: 'Cairo',
fontWeight: FontWeight.bold),),
onTap: () => navigateToDetails(snapshot.data[index]),
),
),
),
//SizedBox(width: 1.0),
Expanded(
flex: 1,
child: Container(child: Image.network(snapshot.data[index].data["image_url"],height: 80.0,width: 80.0)),
),
],
),
),
);
add MainAxisAlignment:MainAxisAlignment.center property to your Row widget
followed code should work for you check this out.
return Card(
child: Container(
alignment: FractionalOffset.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: ListTile(
title: Text(
snapshot.data[index].data["title"],
textDirection: TextDirection.rtl,
style: TextStyle(
fontSize: 14.0,
fontFamily: 'Cairo',
fontWeight: FontWeight.bold),
),
onTap: () => navigateToDetails(snapshot.data[index]),
),
),
),
//SizedBox(width: 1.0),
Expanded(
flex: 1,
child: Container(
child: Image.network(snapshot.data[index].data["image_url"],
height: 80.0, width: 80.0)),
),
],
),
),
);
you are using expanded widget inside row so that both the widget try to get same width and also try to cover whole width possible.
so that, if you want to remove space between row widget then remove expanded widget and play with MainAxisAlignment property of Row to arrange or manage the space.
you can use values like:
MainAxisAlignment.spaceBetween and MainAxisAlignment.spaceEvenly