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.
Related
After many attempts and trying different things, I get the same error ( throw constraintsError ) as soon as I add Expanded, while the error disappears by deleting it,, i I want the upper part to be fixed and the other part to be Scrollable
thanks
SingleChildScrollView(
child: Column(
children: [
Column(
children: [
Container(), // fixed
Row(), // fixed
**Expanded**(
child: Container(
color: constants.kLightGrayColor,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
controller: controller.scrollController,
itemCount: data.posts.length,
itemBuilder: (context, index) {
firstly cannot used Expanded inside SingleChildScrollView.
to work normally pls remove SingleChildScrollView widget and remove outer Column,
used one of Column in green box.
it is small example
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Container(
height: 200,
width: MediaQuery.of(context).size.width,
color: Colors.red,
child: const Center(child: Text("Fixed Box")),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(
title: Text("$index"),
);
},
),
),
],
),
);
}
I cannot seem to get my screen to scroll. I have tried a few variations of the following code but I have not been able to get it to work. I also tried it with a ListView that did not work very well either. Admittedly, I did not try to troubleshoot the ListView for very long because I was assuming the issue was being caused by something else. I have looked on SO and seen a few questions about this topic and they helped me fix some issues, but I cannot seem to get it to work. I do not get any error messages or anything, my screen simply does not scroll. Below you will see the general layout of my code. What am I doing wrong?
class _TripPackagesState extends State<TripPackages> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(...),
GestureDetector(...),
],
),
),
),
Container(
margin: EdgeInsets.only(top: 1.0),
child: SingleChildScrollView(
child: StreamBuilder<QuerySnapshot>(
stream:
Firestore.instance.collection('trip_package').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> docSnapshot) {
if (!docSnapshot.hasData) return const Text('Loading...');
final int docCount = docSnapshot.data.documents.length;
return GridView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: docCount,
itemBuilder: (_, int index) {
DocumentSnapshot document =
docSnapshot.data.documents[index];
return GestureDetector(
child: Container(
margin: EdgeInsets.all(3.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(...),
Row(...),
],
),
),
);
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(...),
);
},
),
),
),
],
),
);
}
}
Try using primary: false in your GridView.builder
I have a problem, when I want to scroll on the screen, the app doesn't scroll. What am I missing?
This is my
code
return Scaffold(
appBar: AppBar(
title: Text('Second Page'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * .7,
child: ListView.builder(
itemCount: itemsDishes.length,
itemBuilder: (context, index) {
return itemsDishes[index];
},
)),
Container(
height: MediaQuery.of(context).size.height * .9,
child: ListView.builder(
itemCount: itemsDrinks.length,
itemBuilder: (context, index) {
return itemsDrinks[index];
},
)),
],
),
),
),
);
As you can see, the column is nested within a SingleChildScrollView
Your inner ListView widgets are capturing the scroll event but don't contain enough items to scroll themselves, and when you're using a SingleChildScrollView an inner ListView is redundant anyway. I'd recommend changing them to Column:
return Scaffold(
appBar: AppBar(
title: Text('Second Page'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
children: itemsDishes,
),
Column(
mainAxisSize: MainAxisSize.min,
children: itemsDrinks,
),
],
),
),
),
);
Remove Containers wrapping your ListViews and set shrinkWrap as well as physics properties.
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: itemsDishes.length,
itemBuilder: (context, index) {
return itemsDishes[index];
},
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: itemsDrinks.length,
itemBuilder: (context, index) {
return itemsDrinks[index];
},
)
You may just not have enough items on your screen!
You can also set physics: const AlwaysScrollableScrollPhysics(), on your SingleChildScrollView.
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,
),
),],),));
}}
In my Flutter project, I have a container with a fixed height. Inside that container I have a Listview.
Here's the code-
return new Scaffold(
appBar: AppBar(
title: Text("All Values"),
),
body: new Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
height: isLoading ? 50.0 : 0,
color: Colors.white70,
child: Center(
child: new CircularProgressIndicator(),
),
),
Expanded(
child: Container(
height: 350,
color: Colors.red,
alignment: Alignment.bottomLeft,
child:
new ListView.builder(
itemCount: data.length-8,
itemBuilder: (BuildContext cxtx, int index) {
return Padding(
padding: const EdgeInsets.fromLTRB(10, 0.0, 10, 0),
child: Container(
child: showCard(index, radius),
),
);
},
controller: _scrollController,
),
),),
],
),
resizeToAvoidBottomPadding: false,
);
The code outputs like below-
So, the problem is I want to align these items at bottom left of the container. I could have done that using reverse: true but I need the list items with the same sequence. So, I need suggestion how can I do that?
You need those items in a row or a column? Follow with a row possibility:
Try this:
return new Scaffold(
appBar: AppBar(
title: Text("All Values"),
),
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
if(isLoading)
Container(
height: 50.0 ,
color: Colors.white70,
child: Center(
child: new CircularProgressIndicator(),
),
),
Expanded(
child: Container(
height: 350,
color: Colors.red,
alignment: Alignment.bottomLeft,
child: new ListView.builder(
itemCount: data.length - 8,
itemBuilder: (BuildContext cxtx, int index) {
return Padding(
padding: const EdgeInsets.fromLTRB(10, 0.0, 10, 0),
child: Container(
child: Text('asdf'),
),
);
},
controller: _scrollController,
),
),
),
],
),
resizeToAvoidBottomPadding: false,
);
StoreConnector<_ViewModel, List<Message>>(
converter: (store) {
// check mark ,reverse data list
if (isReverse) return store.state.dialogList;
return store.state.dialogList.reversed.toList();
},
builder: (context, dialogs) {
// Add a callback when UI render after. then change it direction;
WidgetsBinding.instance.addPostFrameCallback((t) {
// check it's items could be scroll
bool newMark = _listViewController.position.maxScrollExtent > 0;
if (isReverse != newMark) { // need
isReverse = newMark; // rebuild listview
setState(() {});
}
});
return ListView.builder(
reverse: isReverse, // 反转列表,insert数据时,刷新到0,加载更多时,滚动偏移不变
controller: _listViewController,
itemBuilder: (context, index) => _bubbleItem(context, dialogs[index], index),
itemCount: dialogs.length,
);
},
)