how to scroll the screen Listview builder inside column - flutter

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 1,
backgroundColor: appBarColor,
centerTitle: true,
title: const Text('News'),
),
body: Column(
children: [
news.length < 2
? ImageSlideshow(
children: [NewsSlideWidget0(news: news)],
)
: ImageSlideshow(
children: [
NewsSlideWidget0(news: news),
NewsSlideWidget1(news: news)
],
),
Container(
color: Colors.white,
child: ListTile(
// selectedTileColor: Colors.white,
title: Text(news_screen_title, style: news_screen_title_tstyle),
subtitle: Text(news_screen_subtitle),
),
),
news.isEmpty
? const CircularProgressIndicator()
: Expanded(
child: LazyLoadScrollView(
onEndOfPage: () => loadNextPage(),
scrollOffset: 10,
child: ListView.builder(
itemCount: news.length,
itemBuilder: (BuildContext context, int i) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewsInnerScreen(
title: news[i].title,
date: news[i].date,
image: news[i].images[0],
content: parse(news[i].content).body!.text,
),
),
);
},
child: Container(
child: ListTile(
contentPadding: EdgeInsets.all(15),
title: Text(
news[i].title,
),
subtitle: Column(
children: [
Text(
parse(news[i].content).body!.text,
style:
),
Text(
news[i].date,
),
],
),
trailing: ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 100,
minHeight: 300,
maxWidth: 104,
maxHeight: 300,
),
child: ClipRRect(
child: Image(
image: NetworkImage(
news[i].images[0],
),
),
),
),
),
),
),
);
},
),
),
),
],
),
);
}
my screen is like this I want this column to scrollable I tried singlechildscrollview and listview those did not work for me and I use a plugin for pagination and I use more widgets also and I extracted that and u I use image slide show packages for carousel so how can I do that I am new to flutter please let me know

All list builder in Flutter have property called "shrinkWrap"
Just turn it to "true"

Related

ListView doesn't separate objects from doc

I'm trying to create scrollable list of posts, but instead i got static non-scrollable bloc of strings, which is overflowing.
Example:
Oveflowing:
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _writePost,
tooltip: 'Increment',
child: Icon(Icons.create, color: Colors.grey[300]),
),
body: SizedBox(
child: Container(
child: Column(children: [
StreamBuilder<List<Post>>(
initialData: const [],
stream: _socketStream.stream,
builder: (context, snapshot) {
if (_isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
)
],
);
},
),
]))));
}
Moreover, they all go like a single card, without separating.
Edited code, which is scrolling but doesn't separate posts
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _writePost,
tooltip: 'Increment',
child: Icon(Icons.create, color: Colors.grey[300]),
),
body: SizedBox(
height: 500,
child:
StreamBuilder<List<Post>>(
initialData: const [],
stream: _socketStream.stream,
builder: (context, snapshot) {
if (_isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
return Card(child: ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
)
],
) );
},
),
));
}
I'm tried to find error with documentation, but...
Column and Listview take the maximum available height. therefore, the height of Listview which here is a child of Column should be constrained. You can do so by wrapping your ListView inside Expanded:
child: Column(
children: [
Expanded(
child: ListView(
Also, if your list is long, it is not recommended to set shrinkwrap to true. Because it makes the ListView to load all its items when the layout gets built. So it can slow down performance.
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _writePost,
tooltip: 'Increment',
child: Icon(Icons.create, color: Colors.grey[300]),
),
body: SizedBox(
height: MediaQuery.of(context).height*0.8, // add this line
child:
// Container( // do not need this
// child: // and this do not need
// Column(children: [ // and this do not need
StreamBuilder<List<Post>>(
initialData: const [],
stream: _socketStream.stream,
builder: (context, snapshot) {
if (_isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
ListView( // change this to ListView.builder for more performance
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
)
],
);## Heading ##
},
),
// ]) // comment this
// ). // and comment this
)
);
}

Single card is not single

I'm trying to make posts like on Twitter, where every post is a single separated item, but they all go like big single card, without separating. I'm kinda new with Flutter and bad at explanations, but I hope u got it.
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: _writePost,
tooltip: 'Increment',
child: Icon(Icons.create, color: Colors.grey[300]),
),
body: SizedBox(
height: 500,
child:
StreamBuilder<List<Post>>(
initialData: const [],
stream: _socketStream.stream,
builder: (context, snapshot) {
if (_isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
return Card(child: ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
)
],
) );
},
),
));
}
Example of how it looks:
I'm tried to find error with documentation, but...
Write if u need some more code or explanations.
Please help me if you can <3
You need to add each of the mapped item of your data with Card instead of your parent ListView. Something like this:
return ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
...snapshot.data!.map<Widget>(
(post) => Padding(
key: ValueKey(post.id),
padding: const EdgeInsets.symmetric(vertical: 10),
child:
// Use card here.
Card(child: ListTile(
title: Text(
post.content,
style: const TextStyle(fontSize: 20),
),
trailing: MaterialButton(
onPressed: () {
_deletePost(post.id);
},
child: const Icon(
Icons.delete,
size: 30,
),
),
),
),
),
)
],
);
You can try ListView.separated
Try:
List.generate(lentgh, (index) {
return Text("$index"); // custom widget
}),

key board hinding screen in flutter

here is code[enter image description here[][1]][1]
hey I am developing a new app that has a comment section show I put Text field in bottom because of better view but I am having a problem whenever I open my keyboard my half screen gets hide, this is very
bad for user Interface so here I need your help, And when I make resizeToAvoidBottomInset false text field get hide behind keyboard
appBar: AppBar(
elevation: 0.0,
title: Text(
"Comments",
style: TextStyle(color: Colors.black),
),
),
body: Column(children: [
Expanded(
child: Obx(
() => ListView.builder(
itemCount: controller.comments.length,
itemBuilder: (BuildContext context, int index) {
return Comment(
comment: controller.comments[index]['comment'],
userid: controller.comments[index]['userid']);
}),
),
),
Spacer(),
Container(
height: 50,
child: CupertinoTextField(
controller: controller.postComment,
padding: const EdgeInsets.all(8),
prefix: IconButton(
onPressed: () {},
icon: Icon(Icons.emoji_emotions),
),
// decoration: BoxDecoration(border: Border.all()),
suffix: IconButton(
icon: Icon(Icons.send),
onPressed: () {
controller.addComment(
args, FirebaseAuth.instance.currentUser.uid);
},
),
placeholder: "Enter a Comment",
),
)
]),
); ```
[1]: https://i.stack.imgur.com/FER2u.png
I believe you can use SingleChildScrollView if you want to make your content inside column scrollable when keyboard is shown. Here is the example of usage:
SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: 250,
color: Colors.red[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 250,
color: Colors.red[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 250,
color: Colors.yellow[100],
child: const Center(child: Text('Entry C')),
),
],
),
)

How to center an image in Appbar

I'd like to center an image in appbar (As Twitter does in their mobilapps), but I can't find any logic that does that. I tried to wrap the Container with Center() but it didn't work.
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text('Cranes'),
actions: <Widget>[
Container(
// margin: const EdgeInsets.only(right: 75),
child: Image.asset(
'assets/hmf_logo_medium.png',
),
),
FlatButton(
onPressed: () async {
await Provider.of<FlutterSecureStorage>(context, listen: false)
.deleteAll();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => LoginPage()),
(route) => false);
},
child: Text(S.of(context).craneListPageLogoutText,
style: TextStyle(color: Colors.white)),
)
],
),
); }
Try this
AppBar(
leading: Center(
child: Text('Cranes'),
),
title: Image.asset('assets/hmf_logo_medium.png'),
centerTitle: true,
)
You can wrap your all items with row then mainAxisAlignment.spaceBetween can handle that.
AppBar(
title:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Cranes'),
Container(
// margin: const EdgeInsets.only(right: 75),
child: Image.asset(
'assets/hmf_logo_medium.png',
),
),
FlatButton(
onPressed: () async {},
child: Text(S.of(context).craneListPageLogoutText,
style: TextStyle(color: Colors.white)),
)
],
),
),
Following would work :
AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Cranes'),
Image.asset(
'assets/logo.png',
fit: BoxFit.contain,
height: 32,
),
Container()
],
),
)
Result :
in title Property Use your Image. and then make centerTitle:true,
AppBar(
backgroundColor: kWhite,
elevation: 0,
title: Image.asset(kLogoYellow),
centerTitle: true,
)

Flutter dynamic height of ListView

I am developing a Flutter application and I want to dynamically adjust the height of the ListView.
I want the list to have a maximum height of 200. If the height is more than that, user will have to scroll to reach the bottom. If height is below 200, it will take only as much space as needed.
Preview of application: Screenshot. As you can see Restaurants nearby is pushed to the very bottom of the page. I want the ListView to only take height of 200 or less so that the content below isn't pushed to the bottom.
Here is my current code:
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Enter restaurant manually'),
onPressed: () {
print('Button pressed');
},
),
],
),
Flexible(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: 15,
),
),
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
],
),
);
}
You are using Flexible widget, that's why your ListView expands. You have to change Flexible to ConstrainedBox and add shrinkWrap: true to your ListView.
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 200, minHeight: 56.0),
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: 15,
),
),
More info here: https://api.flutter.dev/flutter/widgets/ConstrainedBox-class.html
You can use LimitedBox
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(...),
Divider(),
Row(...),
LimitedBox(
maxHeight: 200.0,
child: ListView.builder(...),
),
Text(...),
],
),
Recommended solution in case when the incoming constraints are unbounded
Consider wrapping the ListView into this
LimitedBox(
maxHeight: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: _itemsCount,
),
),
]
)
),
Note that:
shrinkWrap of ListView is set to true
mainAxisSize of Column is set to MainAxisSize.min
maxHeight of LimitedBox is set to 200
A complete snippet:
import 'package:flutter/material.dart';
class DebugWidget extends StatefulWidget {
#override
_DebugWidgetState createState() => _DebugWidgetState();
}
class _DebugWidgetState extends State<DebugWidget> {
int _itemsCount = 1;
#override
Widget build(BuildContext context) {
Widget child = Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Enter restaurant manually'),
onPressed: () {
print('Button pressed');
},
),
RaisedButton(
child: Text('+1'),
onPressed: () {
setState(() {
_itemsCount += 1;
});
},
),
RaisedButton(
child: Text('-1'),
onPressed: () {
setState(() {
_itemsCount -= 1;
});
},
),
],
),
LimitedBox(
maxHeight: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: _itemsCount,
),
),
]
)
),
Text(
'Restaurants nearby',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
],
),
);
return Scaffold(
body: child,
);
}
}
I found a solution to this problem. you should wrap your ListView with LimittedBox or ConstraintBox and give them maxHeight and set shrinkWrap property of ListView to true. the solution would be something like this.
LimitedBox(
maxHeight: 200,
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: CircleAvatar(
backgroundColor: Colors.cyan,
),
title: Text('Test restaurant'),
subtitle: Text('80m'),
);
},
itemCount: 15,
),
),
I see that this question has never been answered only with giving a fixed height, so here is what works for me.
For some reason if you set the shrinkwrap to true it doesn't look like it is working but it does, the problem is in the padding settings of the ListView, set the padding to edgeinstets.zero. That fixes it for me.
Wrap inside a Flexible
ShrinkWrap true
Padding, zero
and if needed the column to MainAxisSize.min.
Hope it helps some people.
Example of my code:
Flexible(
child: Container(
decoration: BStyles.cardDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text(
'PRODUCTION TASKS',
),
const SizedBox(
height: textVerticalSpacing,
),
Flexible(
child: ListView.builder(
itemCount: recentTasks.length,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return TaskCard(
task: recentTasks[index],
widthInfo: MediaQuery.of(context).size.width * 0.6,
);
},
),
),
const SizedBox(
height: itemSpacing,
),
Align(
alignment: Alignment.centerRight,
child: InkWell(
onTap: () { },
child: const Text(
'View more',
),
),
),
const SizedBox(
height: textVerticalSpacing,
),
],
),
),
),
),
ConstrainedBox(
constraints: BoxConstraints(maxHeight: 200.0),
child: [your child here],
)
This make your child's height not bigger than 200.0
You can always size the ListView container as % of the viewport (assuming of course that the other widgets also are sized in the same manner):
return Container(
height: MediaQuery.of(context).size.height * 0.75,
child: ListView.builder(
itemBuilder: (ctx, index) {
return Card(...