How to implement a Non scrollable listview inside a SingleChildScrollView - flutter

Im trying to implement a non scrollable ListView builder here but can't seem to find how to do it. Reason is because i want everything to be scrollable and i dont want to have a Scrollable widget inside a scrollable parent.
class _DashboardState extends State<Dashboard> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('App Bar Here')),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Hello World'),
Container(
child: ListView.builder(
itemBuilder: (context, index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Container(
color: Color(0xffaaaaaa),
height: 20,
child: Text('Jss One')),
Text(
'English',
style: TextStyle(fontSize: 20),
),
],
),
),
);
},
itemCount: 50,
),
),],),));
}}

class _DashboardState extends State<Dashboard> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('App Bar Here')),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Hello World'),
Container(
child: ListView.builder(
physics: NeverScrollableScrollPhysics() //add this line,
itemBuilder: (context, index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Container(
color: Color(0xffaaaaaa),
height: 20,
child: Text('Jss One')),
Text(
'English',
style: TextStyle(fontSize: 20),
),
],
),
),
);
},
itemCount: 50,
),
),],),));
}}
set physics property to NeverScrollablePhysics() in order to not scroll the lisview

try using physics property of listview
physics: NeverScrollableScrollPhysics()
hope it helps..

The Solution to what i was going for.
What happens here is the ListBuilder widget will build a List of items not in a Scrollable widget. The parent widget itself is scrollable which makes the whole Screen scrollable. To do this, add shrinkWrap: true and physics: NeverScrollableScrollPhysics() to the ListView.builder() property.
class _DashboardState extends State<Dashboard> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('App Bar Here')),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Hello World'),
Container(
child: ListView.builder(
shrinkWrap: true, //add this line
physics: NeverScrollableScrollPhysics() //add this line,
itemBuilder: (context, index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Container(
color: Color(0xffaaaaaa),
height: 20,
child: Text('Jss One')),
Text(
'English',
style: TextStyle(fontSize: 20),
),
],
),
),
);
},
itemCount: 50,
),
),],),));
}}

Related

Scroll To Index in ListView Flutter

In my application I am listing in an appBar several Containers that have the names of product categories, these categories are being listed in the body with their respective products.
The ListView that is in the appBar has the same indexes of the ListView of the body, so the idea was to press the index 'x' in the appBar and the user would be redirected to the index 'x' in the body.
I tried many solutions, one of then was the package https://pub.dev/packages/scrollable_positioned_list, but it did not works because when calling the function to scroll my list just disappears.
Here's de code:
return Scaffold(
backgroundColor: Colors.white,
appBar: PreferredSize(
preferredSize: Size.fromHeight(120),
child: Column(
children: [
AppBar(...),
Expanded(
child: Container(
color: AppColors.primary,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: widget.listaProdutos.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.symmetric(...),
child: GestureDetector(
child: Container(
decoration: BoxDecoration(...),
child: Padding(...),
child: Center(
child: Text(
widget.listaProdutos[index].dsGrupo,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
onTap: () {
SHOULD SCROLL TO INDEX
},
),
);
},
)
),
),
],
),
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: widget.listaProdutos.length,
itemBuilder: (context, indexGrupo) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(...),
ListView.builder(..),
],
);
},
),
),
],
),
),
);
You can use PageView with scrollDirection: Axis.vertical,
class TFW extends StatefulWidget {
const TFW({super.key});
#override
State<TFW> createState() => _TFWState();
}
class _TFWState extends State<TFW> {
final PageController controller = PageController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: PreferredSize(
preferredSize: Size.fromHeight(100),
child: Expanded(
child: ListView.builder(
itemCount: 100,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
controller.animateToPage(index,
duration: Duration(milliseconds: 400),
curve: Curves.easeIn);
},
child: SizedBox(width: 100, child: Text("$index")),
);
},
),
),
)),
body: PageView.builder(
controller: controller,
itemCount: 100,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Container(
color: index.isEven ? Colors.red : Colors.blue,
child: Text("$index"),
);
},
),
);
}
}
Fortunately I was able to resolve the problem. To help members who may have the same doubt I will register here the solution that worked for me. (sorry for the bad English)
Question: Why ScrollablePositionedList wasn't working? (as I mentioned iniatily)
Response: I was using the ScrollablePositionedList within a SingleChildScrollView, and for some reason when using the scrollTo or jumpTo function, the information that was visible simply disappeared. For that reason, I was trying to find a way to get success using a ListView (what came to nothing).
Solution: ... Trying to figure out why the ScrollablePositionedList wasn't working as it should ...
The initial structure was:
body: SingleChildScrollView(
child: Column(
children: [
Container(
child: ScrollablePositionedList.builder(
Changed for:
body: ScrollablePositionedList.builder(
The only reason for all this confusion is that ScrollablePositionedList's indexing functions for some reason don't work as they should if it's inside a SingleChildScrollView. So, take off SingleChildScrollView and all good.

Column/SingleChildScrollView not scrolling

I'm learning flutter to make an app. Here I'm trying to make a page to show the full post. The problem is that the page isn't scrolling as a single unit.
class SinglePostPage extends StatefulWidget {
final Post? post;
const SinglePostPage({Key? key, this.post}) : super(key: key);
#override
State<SinglePostPage> createState() => _SinglePostPageState();
}
class _SinglePostPageState extends State<SinglePostPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: const EdgeInsets.only(top: 22.5),
padding: const EdgeInsets.fromLTRB(0, 5, 0, 6),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const BackButton(),
Row(
children: [
InkWell(
onTap: () {
showDialog(...);
},
child: CircleAvatar(...),
Container(
padding: const EdgeInsets.only(left: 5.4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () {
showDialog(...);
},
child: Text(
widget.post!.author[0].profileName,
),
),
const SizedBox(height: 4),
Text(
showTimeAgo(widget.post!.postTime).toString(),
),
],
),
),
],
),
PopupMenuButton(
icon: const Icon(Icons.more_vert),
itemBuilder: (context) => [...],
),
Container(
margin: const EdgeInsets.fromLTRB(12, 9, 12, 3),
// when the text is longer than the screen height it showed RenderFlex overflowed error so I put constraints. how to show it full and make this scroll
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.54,
minHeight: 50),
child: SingleChildScrollView(
child: Text(
widget.post!.postText,
textAlign: TextAlign.start,
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (widget.post!.postMedia.isNotEmpty)
CarouselSlider.builder(...),
const SizedBox(height: 4.5),
if (widget.post!.postMedia.length > 1)
buildDotIndicator(widget.post!.postMedia),
],
),
],
),
),
Container(
// post reactions row
),
CommentBodyWidget(
postId: widget.post!.postId,
),
],
),
);
}
}
I looked up for other answers and tried wrapping it with SingleChildScrollView, but it didn't work , and ListView with shrinkWrap: true also gave 'Incorrect use of ParentDataWidget' error.
CommentBodyWidget has a listview builder. It's scrolling on its own but the widget above isn't scrolling along with it.
How can I show this whole page and scroll together without having to limit the long post in a constrained container? Please help.
You can wrap body Column with SingleChildScrollView and use shrinkWrap: true, and use physics: NeverScrollableScrollPhysics(),. This will solve the issue.
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
//...
ListView.builder(
itemCount: itemlength,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return Text("item $index");
},
),
/// instead of listView
...List.generate(itemlength, (index) => Text("itemWidget"))
],
),
),
);
But I will encourage you to check CustomScrollView.
In order for the SingleChildScrollView to work, its parent's height should be defined.
You can achieve this by wrapping the SingleChildScrollView in a Container/SizedBox with defined height, or by wrapping it with the Expanded widget.
Pass SingleChildScrollView as body of your scaffold. Also shrinkwrap: true for the ListView is recommended so that it only takes up as much space as required, which will avoid unbounded height errors.
So instead of
...
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
...
Do this
...
Widget build(BuildContext context)
return Scaffold(
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(...
I recommend you to use CustomScrollView.
Try this:
CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column("""HERE PUT YOUR CODE""")
)]
),

implementing nested ListView inside SingleChildScrollView

in this sample code i want to put nested ListView inside SingleChildScrollView, but i get this error:
RenderBox was not laid out: RenderRepaintBoundary#8de00 relayoutBoundary=up1 NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1694 pos 12: 'hasSize'
my code:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'test',
home: Scaffold(
appBar: AppBar(
title: Text("Scrollview Demo"),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: 50.0,
color: Colors.green,
child: Center(
child: Text('message'),
),
),
Expanded(
child: ListView.builder(
itemCount: 30,
itemBuilder: (context, index) {
return ListTile(title: Text("Index : $index"));
},
),
),
],
),
),
),
);
}
}
In ListView you can set
shrinkWrap: true
so that ListView only occupies the space it needed.
To disable the scrolling on ListView so it uses that of SingleChildScrollView you can set the
physics: NeverScrollableScrollPhysics().
You need to remove the Expanded which set the child to take the available screen in case of here is infinite.
Here:
SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: 50.0,
color: Colors.green,
child: Center(
child: Text('message'),
),
),
Flexible(
child: ListView.builder(
itemCount: 30,
shrinkWrap: true,
itemBuilder: (context, index) {
return ListTile(title: Text("Index : $index"));
},
),
),
],
),
)
Instead of using SingleChildScrollView then use Column as the child just use ListView.
return Scaffold(
body: ListView(
children: <Widget>[
Container(
height: 104,
child: Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[],
),
),
),
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
),
],
),
);
Ones I was in the same situation and did like that:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'test',
home: Scaffold(
appBar: AppBar(
title: Text("Scrollview Demo"),
),
body: ListView.builder(
itemCount: 30 + 1,
itemBuilder: (context, index) {
if (index == 0) {
return Container(
height: 50.0,
color: Colors.green,
child: Center(
child: Text('message'),
),
);
}
return ListTile(title: Text('Index : ${index -1}'));
},
),
),
);
}
}

How to avoid other stack containers?

I have a chat widget that I've been having trouble with given the unique header. Finally figured out how to position the TextComposer at the base of the app and all looks great, however the ListView where the chat's occur overlaps the header after a certain number of text entries. I've been trying to figure out how to position the ListView.builder so that it stays below the header (_buildImage and _buildTopHeader) and doesn't overlap such as in the image below. Unfortunately I haven't been having any luck. Any suggestions would be greatly appreciated!
Thanks!
Header Overlap
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: Stack(children: <Widget>[
_buildIamge(),
_buildTopHeader(),
Container(
alignment: Alignment.center,
child: new ListView.builder(
padding: new EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
)),
]),
),
Container(
decoration:
new BoxDecoration(color: Theme.of(context).cardColor),
height: 50.0,
child: _buildTextComposer(),
alignment: Alignment.bottomCenter,
),
],
),
),
resizeToAvoidBottomPadding:false,
);
}
Stack renders its children list in order from top to bottom, with stuff on the bottom rendered over things at the top (it makes sense, I promise). So if you want the ListView to be rendered at the bottom of everything else, put it at the top of the children list:
Stack(
children: <Widget>[
Container(
alignment: Alignment.center,
child: new ListView.builder(
padding: new EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
),
),
_buildIamge(),
_buildTopHeader(),
],
),
Take a try with Positioned
Demo:
import 'package:flutter/material.dart';
class StackPositionPage extends StatefulWidget {
StackPositionPage({Key key, this.title}) : super(key: key);
final String title;
#override
_StackPositionPageState createState() => _StackPositionPageState();
}
class _StackPositionPageState extends State<StackPositionPage> {
var _headerHeight = 100.0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: buildBody(context),
);
}
Widget buildBody(BuildContext context) {
return SafeArea(
child: Column(
children: <Widget>[
Expanded(
child: Stack(children: <Widget>[
_buildIamge(),
_buildTopHeader(),
Positioned(
top: _headerHeight,
left: 0,
right: 0,
bottom: 0,
child: ListView.builder(
padding: new EdgeInsets.all(8.0),
itemBuilder: (_, int index) => Padding(
padding: const EdgeInsets.all(16.0),
child: _buildMessage(index),
),
),
),
]),
),
Container(
color: Colors.blue,
height: 50.0,
alignment: Alignment.bottomCenter,
child: Center(
child: Text("Composer"),
),
),
],
),
);
}
Text _buildMessage(int index) => Text("Message " + (index + 1).toString());
Container _buildTopHeader() {
return Container(
height: _headerHeight,
color: Colors.pink,
child: Center(
child: Text("Header"),
),
);
}
Container _buildIamge() {
return Container(
color: Colors.grey,
);
}
}

Listview not showing inside a Row in Flutter

I am trying to show a listview after some texts in a column. The text shows properly inside the first Row until I add a listview inside the next row. Everything disappears after adding the ListView.
Here is the Code:
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text(
"Prayer Time",
style: TextStyle(fontSize: 20, fontWeight:
FontWeight.normal),
),
],
),
Row(
children: <Widget>[myList()],
),
],
),
),
floatingActionButton: FloatingActionButton(
tooltip: 'Add Alarm',
child: Icon(Icons.add),
backgroundColor: const Color(0xff0A74C5),
),
);
}
Expanded myList() {
return Expanded(
child: ListView.builder(
itemBuilder: (context, position) {
return Card(
child: Text(androidVersionNames[position]),
);
},
itemCount: androidVersionNames.length,
)
);
}
}
change like this:
Expanded(
child: Row(
children: <Widget>[myList()],
),
),
Your ListView should have a fixed Size. Try to wrap the ListView inside a Container.
I run your code and fixed it. Replace your myList() with this code bellow:
Expanded myList() {
return Expanded(
child: Container(
width: double.infinity,
height: 200,
child: ListView.builder(
itemBuilder: (context, position) {
return Card(
child: Text(androidVersionNames[position]),
);
},
itemCount: androidVersionNames.length,
),
)
);
}