Flutter: Scrolling with Nested Widgets - flutter

I have one page in my flutter app that is basically a big list with multiple nested lists. No matter what type of widgets I use, the screen won't scroll properly. It does the scroll where it bounces to the top and doesn't let the user scroll all the way down. How can I get this to be scrollable?
Here is the code from the main page:
body: CustomScrollView(
physics: new AlwaysScrollableScrollPhysics(),
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate([
Container(
margin: EdgeInsets.all(8),
child:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
new AlertItems(ptid: ptid),
])),
Container(
child:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
new OpenAppts(ptid: ptid),
])),
Container(
child:
Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
new OpenLabs(ptid: ptid),
])),
])),
],
),
And then the included AlertItems (as an example) looks like this:
return ListView.builder(
padding: const EdgeInsets.all(15.0),
shrinkWrap: true,
itemCount: snapshot.data.total,
itemBuilder: (context, index) {
newDate = DateTime.parse(
snapshot.data.entry[index].resource.date);
if (index == 0) {
return new Column(
children: <Widget>[
ListTile(
leading: Icon(
Icons.announcement,
color: Colors.orange[400],
),
title: Text(
snapshot.data.total.toString() +
' Open Items ',
style: TextStyle(fontSize: 20)),
),
Divider(height: 5.0),
ListTile(
title: Text(
formatDate(newDate, [m, '/', d, '/', yyyy])),
subtitle: Text(snapshot.data.entry[index].resource
.messageSubject ??
'No Subject'),
leading: Image(
image: AssetImage('images/messaging.png'),
height: 30,
),
contentPadding: EdgeInsets.only(left: 50.0),
),
],
);
}

Setting physics: ScrollPhysics() for both the ListView and the CustomScrollViewshould work.

use NestedScrollView rather than CustomScrollView you can get full expanation and example code here NestedScrollView Flutter Doc

Related

Flutter listview scrolling is not available

I can see 6 list items in my listview widget and I can not scroll the listview although 3 more items are there.
Actually I want to keep this workouts page pretty simple that means I want to avoid using many rows/columns...
I have just a text label at the top left corner and below listview.
What do I have to change to make the listview scrolling?
I already use physics: AlwaysScrollableScrollPhysics(),
appBar: AppBar(
title: Text(title),
),
body: Container(
color: Colors.green,
margin: const EdgeInsets.all(5.0),
child: Column(
children: [
Align(
alignment: Alignment.topLeft,
child: Text("Workouts", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25)),
),
Expanded(
child: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: workouts.length,
itemBuilder: (context, index) {
var workout = workouts[index];
return WorkoutWidget(key: Key(workout.id.toString()), workout: workout);
}),
),
],
),
),
Change physics to NeverScrollableScrollPhysics(), then wrap your Container with SingleChildScrollView widget. You could also omit scrollDirection, because Axis.vertical is already the default value.
appBar: AppBar(
title: Text(title),
),
body: SingleChildScrollView(
child: Container(
color: Colors.green,
margin: const EdgeInsets.all(5.0),
child: Column(
children: [
Align(
alignment: Alignment.topLeft,
child: Text(
"Workouts",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25),
),
),
Expanded(
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: workouts.length,
itemBuilder: (context, index) {
var workout = workouts[index];
return WorkoutWidget(
key: Key(workout.id.toString()),
workout: workout,
);
}),
),
],
),
),

Flutter how to dynamically get the height of my page and my Listview.Builder?

I'm wondering how to get the height of my page dynamically with a Listview.Builder()` inside. This is my page tree:
This is my News.dart
return SafeArea(
child: Scrollbar(
child: SingleChildScrollView(
physics: BouncingScrollPhysics(),
dragStartBehavior: DragStartBehavior.start,
child: Container(
height: MediaQuery.of(context).size.height * 5,
margin: EdgeInsets.all(25),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Column(
...
Later on we have the Listview.Builder()
Expanded(child: Consumer<Model>(
builder: (context, myModel, child) {
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: list.length,
itemBuilder: (ctx, index) =>
ChangeNotifierProvider.value(
value: list[index],
child: GestureDetector(
onTap: () {
setState(() {
},
child: Item(),
),
),
);
})),
Now below my SingleChildScrollView() I have a Container with height of MediaQuery.of(context).size.height * 5, I want to have my complete Screen height dynamic. If I remove the height value, I'm getting the render layout error because there is no parent defining a size. This Page here is Part of a TabbarNavigation and this is the content.
Can anybody tell me how to get the dynamic height of the ListView.Builder() ?
EDIT:
The following is my Tabbar where I define the pages inside the tabbar. One of them is my News.dart
This is the Tabbar.dart:
final List<Widget> _pages = [
NewsScreen(),
TrendScreen(),
OtherScreen(),
];
return Scaffold(
extendBodyBehindAppBar: true,
body: _pages[provider.currentIndex],
bottomNavigationBar: provider.currentIndex != 2
? Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
CustomWidget(),
BottomNavigationBar(
onTap: _selectPage,
backgroundColor: Theme.of(context).primaryColor,
unselectedItemColor: Color.fromRGBO(130, 130, 130, 1),
selectedItemColor: Color.fromRGBO(236, 37, 105, 1),
selectedFontSize: 10,
iconSize: 22,
currentIndex: provider.currentIndex,
type: BottomNavigationBarType.fixed,
selectedLabelStyle: TextStyle(fontSize: 12),
items: [
BottomNavigationBarItem(
backgroundColor: Theme.of(context).primaryColor,
icon: Icon(Icons.home),
title: Text(
'home',
style: TextStyle(
fontSize: 10,
),
),
),
BottomNavigationBarItem(
backgroundColor: Theme.of(context).primaryColor,
icon: Icon(Icons.star),
title: Text(
'News',
style: TextStyle(
fontSize: 10,
),
),
),
BottomNavigationBarItem(
backgroundColor: Theme.of(context).primaryColor,
icon: Icon(Icons.play_arrow),
title: Text('other',
style: TextStyle(
fontSize: 10,
)),
),
],
),
])
: null,
);
}
Credits to #pskink !!
Working with CustomScrollView() instead of SingleChildScrollView(), SliverToBoxAdapter() and SliverList() made everything work like charm!
return SafeArea(
child: CustomScrollView(
//scrollDirection: Axis.vertical,
physics: BouncingScrollPhysics(),
slivers: <Widget>[
// Place sliver widgets here
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(25, 30, 25, 20),
child: SizedBox(
height: 299,
child: Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
...
And a list example:
SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, index) => ChangeNotifierProvider.value(
value: list[index],
child: GestureDetector(
onTap: () {}),
childCount: rrr.length,
)),
You can Use the "Flex" property of the already used Expanded() widget.
first remove the Container at the Top.
return SafeArea(
child: Scrollbar(
child: SingleChildScrollView(
physics: BouncingScrollPhysics(),
dragStartBehavior: DragStartBehavior.start,
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Column(
...
and then,
Column(
children: <Widget>[
Expanded(
flex : 1,
child: Consumer<Model>(
builder: (context, myModel, child) {
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: list.length,
itemBuilder: (ctx, index) =>
ChangeNotifierProvider.value(
value: list[index],
child: GestureDetector(
onTap: () {
setState(() {
},
child: Item(),
),
),
;
})),
]),
API Docs : https://api.flutter.dev/flutter/widgets/Expanded-class.html
Flutter Widget of the Week : https://www.youtube.com/watch?v=_rnZaagadyo

How to scroll individual page when we use tabbar in flutter?

I want to make scrollable page in flutter when we use Tabbar in flutter.
I tried this code but this is not working.
In this code my whole listview I cannot see. How to display whole listview items while using tabbar.
So, how can I solve this problem.
Widget _listofitem() {
return Container(
margin: EdgeInsets.only(top: 10.0),
padding: EdgeInsets.all(8.0),
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: categoryDetail.length,
itemBuilder: (BuildContext context, int index) {
return Container(
padding: EdgeInsets.all(8.0),
width: MediaQuery.of(context).size.width,
height: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.cyanAccent),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: SizedBox(
height: 20,
width: 20,
// child: NetworkImage(categoryDetail[index]),
),
),
SizedBox(
height: 10.0,
),
Text(categoryDetail[index]['category_name'].toString()),
],
),
);
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Text(
'Invitation Card Application',
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.cyan,
centerTitle: true,
bottom: TabBar(
tabs: myTabs,
controller: _tabController,
)
),
body: TabBarView(
controller: _tabController,
children: myTabs.map((Tab tab) {
return Center(
child: Stack(
children: <Widget>[
_listofitem(),
// _ofitem()
],
),
);
}).toList(),
));
}
I want to change page on individual tab click and also do scroll in that individual page. So I display whole my page. What is the solution for it.
In the ListView.builder() widget you have set the property,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
This is preventing the scroll on the list view. If you want to wrap the list view inside the container with the above properties, then wrap the container in the SingleChildScrollView widget.
SingleChildScrollView(
child: Container(),
);
By this, you can have the scroll effect and you will be able to see all the list view items

How to put Expandable list view inside scroll view in flutter?

Hello there i am making a flutter application in which inside ScrollView in need to put Expandable list view.First of all here is my build method.
return Scaffold(
appBar: AppBar(
backgroundColor: app_color,
iconTheme: IconThemeData(
color: Colors.white, //change your color here
)),
//debugShowCheckedModeBanner: false,
//key: scaffoldKey,
backgroundColor: app_color,
body: SingleChildScrollView(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children:<Widget>[
Text("Header"),
new ListView.builder(
itemCount: datas.length,
shrinkWrap: true,
itemBuilder: (context, i) {
return new ExpansionTile(
title: new Text(datas[i].title, style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic),),
children: <Widget>[
new Column(
children: _buildExpandableContent(datas[i]),
),
],
);
},
),
Text("Footer"),
],
),
)
)
);
}
Now the problem is that without SingleScrollChidView this works fine But after using SingleScrollChidView it does not shows anything and gives error RenderBox was not laid out.What is wrong here ? How can i use Expandable list view inside Singlechildscroll view in flutter.
I was able to achieve Expanded ListView within ScrollView with text by
- Use of Wrap inside SingleChildScrollView, provided you make all ListView using shrinkWrap: true
SingleChildScrollView(
child: Wrap(
direction: Axis.horizontal,
children: <Widget>[
_textBody, // text body, with 1000+ words
Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
ListViewOne(_genericListDataOne()),
],
),
),
Column(
children: <Widget>[
ListViewTwo(_genericListDataTwo())
],
)
],
),
),
part of the Code for ListViewOne
ListViewOne(
shrinkWrap: true,
padding: new EdgeInsets.symmetric(vertical: 8.0),
children: // build list here,
);
Give your ListView a fixed height using SizedBox or similar
SingleChildScrollView(
child: Column(
children: <Widget>[
Text("Header"),// tested with 20 of these for scrolling
SizedBox(
height: MediaQuery.of(context).size.height / 2,
child: new ListView.builder(
itemCount: 20,
shrinkWrap: true,
itemBuilder: (context, i) {
return new ExpansionTile(/* whatever */ );
},
),
),
Text("Footer"),// tested with 20 of these for scrolling
],
),
)
Use SizedBox.expand for this problem,
SizedBox.expand(
child : ListView.builder(
itemCount: datas.length,
shrinkWrap: true,
itemBuilder: (context, i) {
return new ExpansionTile(
title: new Text(datas[i].title, style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic),),
children: <Widget>[
new Column(
children: _buildExpandableContent(datas[i]),
),
],
);
},
),
);
Edited answer
Try this, you should get the desired output you are looking for.
You can find the output here.
Column(
children: <Widget>[
Text(),
ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
children:[]),
Text()
]
)
adding below shown code in ListView will allow smooth scrolling of widget
shrinkWrap: true,
physics: ScrollPhysics(),

Flutter GridView is not scrolling

I am adding a header in the grid view. The header is scrolling but when touching grid view. It is not scrolling. I want to scroll header and gridview.
I have used SingleChildScrollView and Expanded. How to solve the please help me.
My code is shown below
Widget ItemGridview() {
return Container(
color: Colors.white,
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Expanded(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
new Text(
'Items of products',
style: TextStyle(fontWeight: FontWeight.w700, fontSize: 18.0),
textAlign: TextAlign.left,
),
GridView.count(
shrinkWrap: true,
primary: true,
padding: EdgeInsets.only(top:15.0),
crossAxisCount: 3,
childAspectRatio: 0.60, //1.0
mainAxisSpacing: 0.2, //1.0
crossAxisSpacing: 4.0, //1.0
children: createCategoryList(),
),
],
),
)
)
]
),
);
}
In my code Items of products is the header.
List<Widget> createCategoryList() {
List<Widget> createCategoryList = List<Widget>();
for (int i = 0; i < documents.length; i++) {
createCategoryList
.add(makeGridCell(documents[i].data['title'], "name", 8,documents[i].data['id']));
}
return createCategoryList;
}
Container makeGridCell(String name, String image, int count, String id) {
return Container(
child: new GestureDetector(
onTap: () {
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
verticalDirection: VerticalDirection.down,
children: <Widget>[
new Container(
child: Image.asset('assets/' + image + ".jpg"),
),
new Container(
color: Colors.white,
padding: EdgeInsets.only(left: 5),
child: new Text(name,
style: TextStyle(
fontWeight: FontWeight.w500, fontSize: 18.0)),
),
],
),
));
}
The createCategoryList() is the list of items in grid written in widget.
I had similar widget tree like you
a gridview.count() wrapped in SingleChildScrollView adding
physics: ScrollPhysics(),
to GridView.count() Widget Solved my problem
source:https://github.com/flutter/flutter/issues/19205
Add physics: ScrollPhysics() property to Gridview. it iwll scroll.
just add some property in GridView
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]),//your card wight
),
],
),
);
}),
));
}
and use like this
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),
],
);
});
}
}
You have some issues related to the Scroll of your widgets, you can reduce the amount of Widgets using Wrap, like this :
Container(
color: Colors.white,
padding: EdgeInsets.all(10),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'Items of products',
style: TextStyle(fontWeight: FontWeight.w700, fontSize: 18.0),
textAlign: TextAlign.left,
),
Padding(
padding: const EdgeInsets.only(top: 15.0),
child: Wrap(
spacing: 20.0,
alignment: WrapAlignment.spaceEvenly,
children:createCategoryList(),
),
],
),
)
)
]
),
);
Add a constraint width or a fixed with to the widget of your item:
return Container(
constraints:
BoxConstraints(maxWidth: MediaQuery.of(context).size.width / 4),
child: new GestureDetector(
I think you need to use some custom scroll view
CustomScrollView(
primary: false,
slivers: <Widget>[
SliverPadding(
padding: const EdgeInsets.all(20.0),
sliver: SliverGrid.count(
crossAxisSpacing: 10.0,
crossAxisCount: 2,
children: <Widget>[
const Text('He\'d have you all unravel at the'),
const Text('Heed not the rabble'),
const Text('Sound of screams but the'),
const Text('Who scream'),
const Text('Revolution is coming...'),
const Text('Revolution, they...'),
],
),
),
],
)
Just ran into this myself, change your primary parameter for the GridView to false, give that a try.
In Gridview.builder scrolling is not working for smaller resolutions like tablet mode,mobile mode then just wrap the Gridview.builder under the listview.builder widget.
SizedBox(
width: screenSize.width,
height: screenSize.height * entry.contentHeightFactor,
child: ListView.builder(
itemCount: 1,
itemBuilder: (context, index) {
return Card(
child: Container(
width: screenSize.width * 0.8,
height: screenSize.height * 0.72,
padding: const EdgeInsets.all(10),
child: GridView.builder(
scrollDirection: Axis.vertical,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
),
padding: const EdgeInsets.all(5),
itemCount: 30,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child:Card(....),
);
},
),
),
);
},
),
),