[enter image description here][1]
Inside My column, there is a stack, a carousel slider,a gridview builder. I want to scroll all of them together. I tried to use singlechildscrollview as you can see in the code below. Please Someone help me how can I scroll those things together.
[1]: https://i.stack.imgur.com/FYexC.png` enter code here`
Scaffold(
backgroundColor: Colors.orange,
// Color(0xFFFFF176),
body: SingleChildScrollView(
child: Column(
children: [
Expanded(
child: Stack(
alignment: Alignment.bottomCenter,
children: [
CarouselSlider(
items: slideImage
.map((image) =>
Builder(builder: (BuildContext context) {
return Container(
height: 200,
width: 500,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
image: DecorationImage(
image: AssetImage(image),
fit: BoxFit.fill),
),
);
}))
.toList(),
options: CarouselOptions(
onPageChanged: (index, reason) {
setState(() {
activeIndex = index;
});
},
height: 300,
viewportFraction: 1,
autoPlay: true,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: AnimatedSmoothIndicator(
activeIndex: activeIndex, count: slideImage.length),
),
],
),
),
SizedBox(
height: 10,
),
Expanded(
child: GridView.builder(
shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
itemCount: menuImage.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.8,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
itemBuilder: (context, index) => Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
color: Color(0xFFFFFDE7),
elevation: 10,
child: GridTile(
child: Column(
children: [
Image.asset(
menuImage[index],
fit: BoxFit.fill,
),
Text(
title[index],
style: TextStyle(fontSize: 18),
),
],
),
),
),
),
),
],
),
),
);
}
}
It would be best if you gave height to the column you are using singlechildeScrollview.
Wrap column widget in container or sizedbox widget and give it height.
column widget has children widget GridView.builder that is wrapped in expanded so gridview.builder will try to take all available height in the column which will be infinite because it's not defined and you will get column covering screen taking infinite screen height in short blank screen.
In flutter, Column will take height as much as it can, SingleChildScrollView child dont have height (infinite). Combine together, Flutter don't know how to render them correctly and causing error.
To solve it, try to determine the height of Column by widgget like SizedBox or determine the mainSize.min.
Another way to solve it is wrap Column by IntrinsicHeight but not recommend cause it heavy.
If it takes too much height. so give height to the column.
like this..
SingleChildScrollView(
child: SizedBox(
height: 500,
child: Column(
children: const [...],
),
),
)
your expanded widget is taking whole space of column try removing it or replacing it with Sizedbox.
Related
In my Flutter app, I have a ListView:
return Scaffold(
body: SafeArea(
child: Container(
color: Colors.blueAccent,
child: ListView(
children: [
Container(
color: Colors.yellow,
height: 100
),
const SizedBox(height: 10),
// How to make this container fill up the remaining height?
Container(
color: Colors.black,
),
],
),
),
),
);
This produces the following view:
Question: How can I make the second box (with black background color) fill up the remaining space? If the content of the box exceeds the remaining space, the ScrollView will enable scrolling.
Is this possible?
There is a better option here using SliverFillRemaining in combination with CustomScrollView instead of a ListView
in your case the code will look like this.
Container(
color: Colors.blueAccent,
child: CustomScrollView(
shrinkWrap: true, // or false
slivers: <Widget>[
SliverToBoxAdapter(
child:Container(
color: Colors.yellow,
height: 100
),),
SliverToBoxAdapter(
child: SizedBox(height: 10),),
// use SliverFillRemaining to make this container fill up the remaining height?
SliverFillRemaining(
hasScrollBody: false, // if using a column, so the widgets in it, doesn't scroll
child:Container( //this container will fill the remaining space in the ViewPort
color: Colors.black,
),
) ,
],
),
),
Fill the remaining space of a ListView means filling the infinite height. I will prefer using Stack as body in this case, hope you can simply archive this.
How can we do without stack?
In this case, we can get the height and use it on Column and using Expanded on inner child that will fill the remaining spaces even for dynamic height.
I prefer using LayoutBuilder to get height.
body: LayoutBuilder(builder: (context, constraints) {
return SafeArea(
child: Container(
color: Colors.blueAccent,
child: ListView(
children: [
SizedBox(
// 1st child of listView
height: constraints.maxHeight,
child: Column(
children: [
Container(color: Colors.yellow, height: 100),
const SizedBox(height: 10),
Expanded(
child: Container(
color: Colors.black,
),
),
],
),
)
],
),
),
);
}),
You can get size and then set a proportion for each...
And set NeverScrollableScrollPhysics() to ensure no slight scrolling, as per below this appears to get what you are seeking.
Widget build(BuildContext context) {
Size _size = MediaQuery.of(context).size;
return Container(
child: Scaffold(
body: SafeArea(
child: Container(
color: Colors.blueAccent,
child: ListView(
physics: NeverScrollableScrollPhysics(),
children: [
Container(color: Colors.yellow, height: _size.height * 0.20),
SizedBox(height: _size.height * 0.10), // How to make this container fill up the remaining height?
Container(
height: _size.height * 0.70,
color: Colors.black,
),
],
),
),
),
));
}
}
Try below code hope its helpful to you. use MediaQuery here. add MediaQuery height to your black container
Refer blog also here for relative to screen size
Container(
color: Colors.blueAccent,
child: ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
children: [
Container(
color: Colors.yellow,
height: 100,
),
const SizedBox(height: 10),
// How to make this container fill up the remaining height?
Container(
color: Colors.black,
height: MediaQuery.of(context).size.height,
),
],
),
),
Your result screen->
I am new to Flutter and was practicing its UI where I came across a situation where I had a list where each list element have an image on the left and some text on right.
Below is my approach to that
child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 20),
children: [
const SizedBox(height: 5),
Row(
children: [
Container(
height: 80,
width: 80,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: const DecorationImage(
image: NetworkImage('http://images.unsplash.com/photo-1555010133-d883506aedee?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max'),
fit: BoxFit.cover
)
),
),
const SizedBox(width: 10),
Container(
color: Colors.green,
height: 80,
width: 280,
)
],
),
],
),
Here I am specifying width individually for both containers which is not an efficient way to do this since phone sizes may vary.
Below is the result for above block of code
Screenshot of the app screen
I tried specifying crossAxisAlignment: CrossAxisAlignment.stretch to the Row() but it throws an error as below
The following assertion was thrown during performLayout():
BoxConstraints forces an infinite height.
How can I achieve this? Please assist
Thank you
Wrap the widget with an Expanded inside the row:
Row(
children: [
...otherChildren,
Expanded(
child: Container(
color: Colors.green,
height: 80,
),
),
],
),
Use ListView.builder with ListTile widgets. It has a leading widget (normally an icon or an avatar) to the left, text in the middle and trailing widget (normally an icon), each of which is optional.
ListView.builder(
itemCount: ...,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: const CircleAvatar(
radius: 20.0,
foregroundImage: NetworkImage(...),
),
title: Text(...),
subtitle: Text(...),
trailing: ...,
onTap: () => ...,
);
},
)
I'm making an application in flutter.
And i wanna show some list of items using GridView, showing 3 items in a row. And make their size flexible depend on the devices.
But Actually what i coded doesn't work properly.
When device screen is somewhat narrow, they shrink and messed up like this.
But when the device screen become wider, the size of image doesn't expand but only the spaces between the items expanded like below.
I wanna make the pictures fill the screen. How can i make it?
Thank you for concerning my question, and i'm sorry about the foreign languages in the picture.
return Scaffold(
appBar: AppBar(
title: Text("${getUnitBookClassTitlebyTag(tag!)} 목록"),
backgroundColor: Color(COLOR_PRIMARY),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: CustomScrollView(
primary: false,
slivers: <Widget>[
SliverPadding(
padding: const EdgeInsets.all(20),
sliver: SliverGrid.count(
crossAxisSpacing: 10,
mainAxisSpacing: 10,
crossAxisCount: 3,
children: <Widget>[
for (UnitBook _curUnitBook in unitBookList!)
UnitBookDisplay(
bookData: _curUnitBook,
imageHeight: null,
imageWidth: null),
],
),
),
],
)),
);
/***
Widget build(BuildContext context) {
//bookDataReplace();
//debugPrint('cover : ${bookData!.coverUrl!}');
//debugPrint('cover : ${bookData!.coverUrl!.replaceAll('\\/', '/')}' );
if (bookData == null) debugPrint('bookData is null!!');
return Column(
children: [
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
DetailScreen(book: convertUnitBooktoBook(bookData!)),
),
);
},
child: Expanded(
child: Container(
margin: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 10.0),
height: imageHeight,
width: imageWidth,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
boxShadow: [
BoxShadow(
color: Colors.black54,
offset: Offset(0.0, 4.0),
blurRadius: 6.0,
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: (bookData!.coverUrl == null)
? (Image(
image: AssetImage('images/default_book_cover_image.png'),
fit: BoxFit.cover,
))
: (Image.network(
'${bookData!.coverUrl!.replaceAll('\\/', '/')}',
fit: BoxFit.cover,
)),
),
),
),
),
SizedBox(
child: Text((bookData!.title == null) ? 'unNamed' : bookData!.title!,
overflow: TextOverflow.ellipsis),
width: imageWidth,
),
],
);
}
While using SliverGrid or GirdView, childAspectRatio decide its children size. While children having fixed height on
child: Expanded(
child: Container(
margin: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 10.0),
height: imageHeight, //<- here
Bottom RenderFlex overflowed occurs only when SliverGrid failed to provide enough height for the children.
You can try removing fixed height from here only UI don't face any issue, but for better design purpose use childAspectRatio on SliverGrid.count, something like
SliverGrid.count(
crossAxisCount: 3,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 3 / 4,// width/height : check and change the way you want.
children: ....
Also, you can try Wrap.
#_#
I was thinking to make the widgets inside the GridView to have a different height according to their dynamic content height, and those widgets are Containers with an Expanded Column inside. But it then gave me this error "Incorrect use of ParentDataWidget".
The widget looks like this:
Container(
decoration: BoxDecoration(
color: someColor,
borderRadius: BorderRadius.circular(17),
),
child: Expanded(
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(17),
child: AspectRatio(
aspectRatio: 5 / 3,
child: Image.network(someImageUrl, fit: BoxFit.cover),
),
),
SizedBox(height: 10),
Text('Group name'),
Text('Group desc'),
SizedBox(height: 10),
Expanded(
child: Row(
children: List.generate(
_group.popIds.length,
(_) => SizedBox(width: 50, height: 50),
),
),
),
Text('Hello')
],
),
),
);
And this is the screen that holds those widgets:
Scaffold(
body: Padding(
padding:
const EdgeInsets.only(left: 17.0, right: 17.0, top: 50),
child: StaggeredGridView.countBuilder(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 20,
itemCount: 50,
itemBuilder: (context, index) => GroupItem(),
staggeredTileBuilder: (index) => StaggeredTile.fit(1),
),
),
);
And the error message looks like this:
**
Incorrect use of ParentDataWidget.
The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type ParentData.**
Are there some genius can help me with this issue, since I've been struggling with it for a whole day!~ #_#
This is because you are using Expanded inside a container.
Expanded should be used only inside Column, Row, or Flex widgets.
In your first code snippet, remove the first Expanded widget that's inside container and wrapping your column, but you can keep the second Expanded widget which is wrapping the row, because this expanded is inside a column, and then the error should go away.
I am using a CustomScrollView. I have added a few slivers in it but one of my children has to be a stack which has a list as on of its two children. I tried using SliverToBoxAdapter but that makes the list in the stack non scrollable which is the obvious behaviour. Is there a way to to write some kind of SliverToSliverAdapter? I tried reading the SliverPadding but its looks too complicated for me to understand. Below is my code:
CustomScrollView(
key: PageStorageKey<String>(name),
slivers: <Widget>[
SliverOverlapInjector(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context)),
SliverToBoxAdapter(
child: Stack(
children: <Widget>[
Container(
width: double.infinity,
height: 50,
decoration: BoxDecoration(color: pink),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: ListView.builder(
padding: const EdgeInsets.all(0),
shrinkWrap: true,
itemBuilder: (context, index) {
return buildSongRow(songs[index]);
},
itemCount: songs.length,
),
)
],
)),
],
);
Stack widget use parent's size by default. While parent widget is CustomScrollView that decide it's size mean, it will get infinite height. To solve this issue, we can wrap Stack with SizedBox(height:x).
Next issue comes on Stack about scrolling and widget visibility. Widget render prioritize bottom to top and same for the scroll event. While Container(height:50) is the first child of Stack, it will be paint behind ListView and in this case we can have full-scroll event on ListView.
We can move Container<height:50> at the bottom to paint it over ListView. In this case, scroll-event won't work on Container<h:50> portion.
We can wrap Container<h:50> and ListView with SizedBox by providing height and use Align or Positioned widget to place them on Stack. Also, we can increase itemCount+1 and use an empty SizedBox(height:50)(on index 0) that will take same amount of height as Container(height:50) and help to view only for 1st time on Stack.
I am using LayoutBuilder to get the size/constraints of screen.
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => CustomScrollView(
slivers: [
const SliverAppBar(
title: Text("Stack On CustomScrollView"),
),
SliverToBoxAdapter(
child: SizedBox(
height: constraints.maxHeight * .3, // used by stack
child: Stack(
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
// dont need to use sizedBox here, height is fixed by container's height:50
height: 50,
color: Colors.pink,
alignment: Alignment.center,
child: const Text("Stack Child: Container<height: 50>"),
),
),
Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: constraints.maxHeight * .3 - 50,
child: ListView.builder(
itemCount: 4,
itemBuilder: (context, index) => Container(
alignment: Alignment.center,
height: 50,
color: index.isEven
? Colors.deepOrange
: Colors.deepPurple,
child: Text("ListViewItem:$index"),
),
),
),
),
],
),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
...List.generate(
44,
(index) => Container(
height: 100,
alignment: Alignment.center,
color: index.isEven ? Colors.cyanAccent : Colors.blueGrey,
child: Text("SliverList $index"),
),
),
],
),
),
],
),
),
);