I want to show a list of comments and so far i have achieve
Code is as below:
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: CommentList(
commentStream: commentBloc.commentStream!,
articleId: widget.articleId!,
),
),
...
and the code for CommentList is:
return StreamBuilder<QuerySnapshot>(
stream: commentStream,
builder: (context, snapshot) {
return snapshot.hasData && snapshot.data!.docs.length > 0
? ListView.builder(
padding: EdgeInsets.only(bottom: 15.0),
reverse: true,
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot ds = snapshot.data!.docs[index];
return CommentTile(
comment: ds["comment"],
commentterName: ds["commentedBy"],
timeAgo: ds["commentAt"],
avatar: ds["avatarUrl"],
);
})
...
How i can achieve this ?
There is a reverse option inside the listview.builder() widget make it true
Related
I'm creating a chat feature in flutter but noticed this behavior on IOS that doesnt shrink the list so you can see the last sent message. How can I have the listview builder shrink to show the last message when the keyboard appears?
Note: This issue doesn't happen on Android
Scaffold(
resizeToAvoidBottomInset: true,
body: Stack(
children: <Widget>[
StreamBuilder(
stream: _chats,
builder: (context, snapshot) {
if (!snapshot.hasData) return Container();
return snapshot.hasData
? GestureDetector(
onPanDown: (_) {
FocusScope.of(context).requestFocus(FocusNode());
},
child: ListView.builder(
shrinkWrap: true,
controller: _scrollController,
padding: EdgeInsets.only(top: 10, bottom: 100),
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
return MessageWidget(
tripId: widget.docId,
uid: snapshot.data.docs[index].data()["uid"],
messageId: snapshot.data.docs[index].id,
message: snapshot.data.docs[index].data()["message"],
sender: snapshot.data.docs[index].data()["senderName"],
sentByMe: widget.uid ==
snapshot.data.docs[index].data()["uid"],
mediaFileUrl:
snapshot.data.docs[index].data()["mediaFileUrl"],
);
}),
)
: Container();
},
);
]
)
)
I think you can try the 'reverse' property from the ListView.builder.
Tell me if this example didn't fit your needs, can you share us your code ? (I didn't see why you use a Stack and what could be the issue around that).
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: Stack(
children: <Widget>[
StreamBuilder<dynamic>(
builder: (context, dynamic snapshot) {
return GestureDetector(
onPanDown: (_) {
FocusScope.of(context).unfocus();
},
child: ListView.builder(
reverse: true,
shrinkWrap: true,
itemCount: 100,
padding: const EdgeInsets.only(top: 10, bottom: 10),
itemBuilder: (context, index) {
return ListTile(title: Text(index.toString()));
},
),
);
},
),
],
),
),
Container(
padding: const EdgeInsets.all(8),
color: Colors.black12,
child: const TextField(),
),
],
),
);
}
}
I'm new to flutter. I have to render widgets according to an API response, which is JSON in a list.
This is one of the custom widgets I have written for it. I have one for every row.
Widget testwidget2() {
return FutureBuilder<List<inspectionOrder>>(
future: createIO_Service.viewinspection_Service(),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<inspectionOrder> data = snapshot.data;
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: data.length,
itemBuilder: (context, index) {
return Container(
height: 50,
child: Center(child: Text(data[index].RoomType)),
);
});
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
);
}
I use a series of rows inside a listview to render these widgets.
ListView(
// decoration: BoxDecoration(
// border: Border.all(color: Colors.blueAccent,width: 5)),
padding: const EdgeInsets.all(15.0),
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded( child: workordertile()),
But the problem is the whole data is rendered in one go (See Picture 1). But I want it to be rendered as shown in the second picture. The application in the second picture is written ionic, of which I have no idea at all. Picture 1
Picture 2
you should use "lazyloading(pagination,etc)"
you can use this package:https://pub.dev/packages/pagination
This is my Json data:
call_record: [
{
"machine_location":"Restaurant",
"allocation_date:"2008-08-31"
"status":"C",
"customer_address":"pune"
}
{
"machine_location":"Restaurant",
"allocation_date:"2008-08-31"
"status":"N",
"customer_address":"pune"
}
{
"machine_location":"Restaurant",
"allocation_date:"2008-08-31"
"status":"O",
"customer_address":"pune"
}]
In my app i want to show data in listview whose date is allocation_date=2008-08-31
Here is my code for display data in ListView:
Widget todayCall(BuildContext context,resultCheck3){
return Container(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
child:Text("Today's Calls"),
),
],
),
FutureBuilder(
future: api3,
builder: (context,snapshot){
if (snapshot.data != null) {
return Container(
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext conxt, int index) {
return Card(
child: Padding(
child: ExpansionTile(
title: Text('${snapshot.data[index]['customer_name']}')
subtitle: Text('${snapshot.data[index] ['error_message']}'"\n"'${snapshot.data[index]['allocation_date']}'
trailing: Icon(Icons.arrow_drop_down,size: 30.0,
children: <Widget>[
ListTile(
title: Text("Machine Model",style: TextStyle(fontSize:13)),
subtitle: Text('${snapshot.data[index]['machine_type']}')
),
ListTile(
title: Text("Location",style: TextStyle(fontSize:13)),
subtitle: Text('${snapshot.data[index]['location_address']}')
),
])))
}))
}}))])
I called this method in Body():
body: Stack(
children: <Widget>[
ListView(
children: <Widget>[
callSummary(context,resultCheck2),
todayCall(context,resultCheck3),
],
),
],
),
[now in my output all data in list view ][1]
[1]: https://i.stack.imgur.com/B3VIz.png .show data whose allocation_date is 2008-08-31
Before returning a widget in the future builder, you can check if the date condition is satisfied.
if (snapshot.data != null) {
return Container(
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext conxt, int index) {
if(snapshot.data[index]['allocation_date'] == '2008-08-31'){
return Card(.....
.
.
.
else{
return Container(height: 0); //return a container with zero height in the else case because you cant return a null and your return must be a widget
}
.
.
.
You can create a filter icon above the listview, so you can use the date picker to select the date and based on the date you can filter the list and show it in your list view.
let me know if this works for you.
Thanks
Hi I am trying to list data from JSON to Listview Builder . But Flutter is giving me this error: Column's children must not contain any null values, but a null value was found at index 0
I tried to map each one like this inside the listview
alo[Index]['rewards'].forEach((k, v) {
Text(v['name']);
}),
Here is my full code:
shrinkWrap: true,
itemCount: alo.length,
itemBuilder: (BuildContext ctxt, int Index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
alo[Index]['rewards'].forEach((k, v) {
Text(v['name']);
}),
],
),
));
});
Is there any solution to this? Thank you!
The thing is forEach() doesn't return anything, you could use map() instead, like this:
children: alo[Index]['rewards'].values.map<Widget>((v) => Text(v['name'])).toList()
If you want to add more widgets, you could do something like this:
Column(
children: <Widget>[
Column(
children: alo[Index]['rewards']
.values
.map<Widget>((v) => Text(v['name']))
.toList(),
),
Text('Other widget'),
],
)
You have two options, if you don't have any rewards then you can
a) Leave an empty card
shrinkWrap: true,
itemCount: alo.length,
itemBuilder: (BuildContext ctxt, int Index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
alo[Index]['rewards']!=null?
alo[Index]['rewards'].forEach((k, v) {
return Text(v['name']);
}):SizedBox()
],
),
));
});
or
b) don't render any card
shrinkWrap: true,
itemCount: alo.length,
itemBuilder: (BuildContext ctxt, int Index) {
return alo[Index]['rewards']!=null?Card(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
alo[Index]['rewards'].forEach((k, v) {
return Text(v['name']);
}),
],
),
)):SizedBox();
});
In FutureBuilder, I need to create Wrap with elements but I don't know how.
FutureBuilder(
future: _getCategories(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.data == null){
return Text("Wait...");
}else{
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index){
return Text(snapshot.data[index].category);
},
);
}
},
)
I need to replace ListView.builder with something like Wrap.builder or something else.
Let's say this is your List:
List<int> _items = List.generate(10, (i) => i);
You can use it in Wrap:
Using List.map
Wrap(
direction: Axis.vertical,
children: _items.map((i) => Text('Item $i')).toList(),
)
Using for-each
Wrap(
direction: Axis.vertical,
children: [
for (var i in _items)
Text('Item $i'),
],
)
To answer your question:
Wrap(
children: snapshot.data.map((item) => Text(item.category)).toList().cast<Widget>(),
)
Here's a solution,
List tags = ['one','two'];
Wrap(
children: [
for (var item in tags)
Padding(
padding: const EdgeInsets.all(8.0),
child: Chip(
label: Text(item),
),
)
],
),