Expand Widget to fill remaining space in ListView - flutter

As in the image shown above, I want widget 2 to always be at least the height of the remaining space available.
But widget 2 might contain so many ListTiles so that they can not be displayed without scrolling. But scrolling should affect widget 1 and widget 2. What is the best way to implement something like this?

Wrap Widget 2 in an Expanded Widget.
To scroll both Widget 1 and Widget 2, wrap both of them in a SingleChildScrollView Widget.

If you can distinguish between the case with a few and many elements (for example during loading), you can use CustomScrollView with SliverFillRemaining for this:
var _isLoading = true;
#override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
_buildWidget1(),
_buildWidget2(),
],
);
}
Widget _buildWidget1() {
return SliverToBoxAdapter(
child: Container(height: 400, color: Colors.blue),
);
}
Widget _buildWidget2() {
if(_isLoading) {
return SliverFillRemaining(
hasScrollBody: false,
child: Center(child: const CircularProgressIndicator()),
);
} else {
return SliverFixedExtentList(
delegate: SliverChildBuilderDelegate(
_buildItem,
childCount: childCount,
),
itemExtent: 56,
);
}
}

A simple way to do that would be to place your widgets in Column and wrap it with a single child scroll view. For the ListView use shrinkWrap as true and physics you can set to NeverScrollableScrollPhysics
Here is an example
SingleChildScrollView(
child: Column(
children: [
Container(
height: MediaQuery.of(context).size.height / 2,
color: Colors.red,
),
ListView.builder(
shrinkWrap:true,
physics:NeverScrollableScrollPhysics(),
itemCount: 100,
itemBuilder: (context, index) => Text("$index"),
),
],
),
);
Hope this helps!

var widgetHeight = MediaQuery.of(context).size.height - fixedSize;
return SingleChildScrollView(
child: Container(
height: widgetHeight,
child: Widget2
)
)

Related

Two direction scrolling in data table flutter

I made a DataTable in flutter and it has about 10 columns and that's more than what the screen can handle so I wrapped the DataTable inside a SingleChildScrollView widget and this solution worked fine until the rows inside the DataTable grew up and exceeded the screen height and I couldn't scroll down because of the scroll direction is set to horizontal in the SingleChildScrollView widget!
And as a temporary solution, I wrapped the DataTable inside a fittedBox inside the SingleChildScrollView but this doesn't solve the whole problem and still, there is some responsibility issues.
What I need is a way to make the DataTable scrollable in both directions horizontally and vertically.
This is my code
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(16),
child: Card(
child: Container(
padding: const EdgeInsets.all(16),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: FutureBuilder(
future: getCategories(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
return FittedBox(
child: DataTable(
headingRowColor: MaterialStateProperty.resolveWith(
(states) => Colors.grey.shade900),
columns: _columns,
rows: _rows,
),
);
}
},
),
),
),
),
);
}
The easiest solution I know, is to wrap the SingleChildScrollView in a second SingleChildScrollView.
https://stackoverflow.com/a/57539405/1151983
But there are also other approaches:
https://stackoverflow.com/a/63546017/1151983

how to Add some design at top after that listview with dynamic size list and then below some some design for advertisement and comment in flutter

Scaffold(
appBar: AppBar(
title: Text("Design test..."),
),
body: Container(
margin:EdgeInsets.fromLTRB(0, MediaQuery.of(context).padding.top, 0, 0
),
child: Column(
children: [
Container(//for Some Kind of design at top),
Column(
children: [
ListView.builder(
itemCount: listLength.length,
itemBuilder: (BuildContext buildContext, int index) {
return ListTile(title: Text("hello world")
);
}),
//i want to add some design here after the list view for advertisement and comment
],
),
],
),
),
);
my listview.builder() item length is dynamic so i want to expand my list view as much as it requied and when it ends i need some design just like youtube privious design where on the top video player after that video list and at the end comment part.thank you.
Yes you can achieve this, Refer to this code.
use the build method like this.
#override
Widget build(BuildContext context) {
return Scaffold(
body : ListView(
//Base Listview, it can be scrollable if content is large also
children:[
Container(
//Sample widget you can use your own
child:Text("Here is some design At Top")
),
ListView.builder(
//use shrinkWrap:true and physics:NeverScrollableScrollPhysics()
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 10, //it can be dynamic and null checks can be appield,
itemBuilder: (context, index){
return Text("ListItem $index");
},
),
Container(
//Sample widget you can use your own
child: Text("Some Design for Ads")
),
Container(
//Sample widget you can use your own
child: Text("Some Design for Commentes")
)
]
)
);
}
Mark answer as right if it helped !!

Use of Listview.builder makes the screen go away

I want to show Listview underneath my two widgets but when i hot reload, nothing happens and if i run again, UI shows blank screen. If i remove Listview.builder it works fine.
Below is my code.
import 'package:flutter/material.dart';
import 'package:plant_clone/constants.dart';
import 'package:plant_clone/model/model.dart';
import 'package:plant_clone/screens/home/components/header_with_searchbox.dart';
import 'package:plant_clone/screens/home/components/title_with_more_btn.dart';
import 'package:plant_clone/viewmodel/recommended_plants_viewmodel.dart';
class Body extends StatelessWidget {
RecommendedPlantViewModel recommendedPlantViewModel =
new RecommendedPlantViewModel();
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
recommendedPlantViewModel.setWidgetsData();
return SingleChildScrollView(
child: Column(
children: [
HeaderWithSearchBox(size: size),
TitleWithMoreButton(
title: "Recommended",
press: () {},
),
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) {
return Card(
child: ListTile(
onTap: (){},
title: Text('Hello'),
),
);
})
],
),
);
}
}
It doesn't look like there's any other way than setting height constraint using a SizedBox that's wrapping a ListView.
Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: size.height,
child: ListView.builder(
...
),
),
],
)
https://flutter.dev/docs/cookbook/lists/horizontal-list
i think it happened because the list view should have a height,,
the esiest way is to test that put it inside a container and give a height to it..
and the second way is wrap the listview inside a Expanded widget and it will fix ..
if not then post the error from debug log
In order to make this to work, you must wrap your ListView with a Container and define the height property as it is part of a Column. You also need to wrap the widget returned by the itemBuilder with a Container and define the width property as the scrollDirection is set to Axis.horizontal.
Container(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) {
return Container(
width: 100,
child: Card(
child: ListTile(
onTap: () {},
title: Text('Hello'),
),
),
);
},
),
)

Flutter ListViewBuilder with 2 different types of elements (eg. profile pic on top and profile details list after that)

I'm aiming for a page that looks like this -
ListView
[Profile _ Image] {Swiper}
[SizedBox]
[Profile Detail-1 ]{Text}
[Profile Detail-2 ]{Text}
[Profile Detail-3 ]{Text}
[Profile Detail-N ] {Text}
I looked at the Flutter cookbook example of MultiList
The cookbook expects all items in the listview to implement the same class. What if this is not possible.
I have tried using index of ListViewBuilder to return Widget based on index.
Is that the right approach? Shall I be doing something completely different - like siglechildScrollView?
Thanks!
Edit1-
Current Code that I'm using -
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) {
this._feedBloc.loadMore();
}
return false;
},
child: ListView.builder(
padding: EdgeInsets.only(bottom: 72),
itemCount: this._postItems.length + 1,
itemBuilder: (context, index) {
if (this._postItems.length == index) {
if (this._isLoadingMore) {
return Container(
margin: EdgeInsets.all(4.0),
height: 36,
width: 36,
child: Center(
child: CircularProgressIndicator(),
),
);
} else {
return Container();
}
}
if(index==0){
return WdgtProfileImage();}
else if(index==1){
return SizedBox(2.0);}
return WdgtUserPost(
model: this._postItems[index],
onPostClick: onPostClick,
);
//return postItemWidget(
// postItem: this._postItems[index], onClick: onPostClick);
}),
);
You can use a CustomScrollView instead of the normal Listview.builder. The CustomScrollView takes in a list of slivers to which you can pass/use a SliverList to build a list.
CustomScrollView(
slivers: <Widget>[
//A sliver widget that renders a normal box widget
SliverToBoxAdapter(
child: WdgtProfileImage(),
),
//A sliver list
SliverList(
//With SliverChildBuilderDelegate the items are constructed lazily
//just like in Listview.builder
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return WdgtUserPost(
model: _postItems[index],
onPostClick: onPostClick,
);
},
childCount: _postItems.length,
),
),
if (_isLoadingMore)
//your loading widget shown at the bootom of the list
SliverToBoxAdapter(
child: Container(
margin: EdgeInsets.all(4.0),
height: 36,
width: 36,
child: Center(
child: CircularProgressIndicator(),
),
),
),
],
)
Additional links to docs:
SliverList
SliverChildBuilderDelegate
SliverToBoxAdapter

How to Center SingleChildScrollView but make background stretch to fill screen?

I am use Flutter for web for make website. I want make webpage scroll when user scroll down like normal website.
I am try use Stack so I can place custom background behind widgets. This background must scroll when user scroll (must stick to widgets in front so background change).
(I cannot set background color using Scaffold because my background is use CustomPainter)
But I want center the widgets on webpage, so I wrap SingleChildScrollView in Center widget. But now on large horizontal screen the CustomPaintWidget() is not fill screen (there is blank space). I have try replace my CustomPaintWidget() with Container to test, but same issue.
Here my code:
Center(
child: SingleChildScrollView(
child:Stack(children: <Widget>[
CustomPaintWidget(),
Widgets(),
],),
Anyone know solution?
How to center widgets but also make background stretch?
Thanks!
SingleChildScrollView by definition shriknwraps it's child.
What you should try is
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: ConstrainedBox(
//Use MediaQuery.of(context).size.height for max Height
constraints: BoxConstraints(minHeight: MediaQuery.of(context).size.height),
child: Center(
child: //Widget,
),
),
);
I think you can try something like:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
CustomPaintWidget(),
Center(
child: SingleChildScrollView(
child: Widgets(),
),
)
],
));
}
read that post, I think is all you need https://medium.com/#swav.kulinski/spike-parallax-in-flutter-seven-lines-of-code-16a1890d8d32
I know it is too late to answer but s.o may need it in future
You have to use Stack
for instance:
your MainClass:
class _BodyState extends State<Body> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
ScrollViewClass(),
Column(
children: [
//YOUR ITEMS
]),
);
ScrollviewClass:
class ScrollViewClass extends StatefulWidget {
#override
_ScrollViewClassState createState() => _ScrollViewClassState();
}
class _ScrollViewClassState extends State<ScrollViewClass> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.only(top: 260, bottom: 100),
child: ListView(
children: [
Container(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: ConstrainedBox(
//Use MediaQuery.of(context).size.height for max Height
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height),
child: Column(
children: [
//ADD YOUR ITEMS LIKE IMAGE, TEXT, CARD ETC...
Center(child: Image.asset('assets/app_name.png')),
Center(child: Image.asset('assets/app_name.png')),
Center(child: Image.asset('assets/app_name.png')),
Center(child: Image.asset('assets/app_name.png')),
Center(child: Text('fdgdfg')),
Center(child: Text('fdgdfg')),
],
)),
),
)
],
),
));
}
}
I know this is not the OP's scenario, but for others - If there is something above your scroll view, using the full height of the page will cause the scrollview to scroll prematurely, because the combined height of the widgets is now greater than the page height. Use LayoutBuilder instead of MediaQuery.of(context).size.height.
LayoutBuilder(builder: ((context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight),
child: Center(child: child)),
);
})