Reputation: 390
I am creating a chat with firebase in flutter and I want that when the listview builder completes it can go to the end of the list (Last message).
This is what my buildmethod looks like:
return Scaffold(
backgroundColor: Color(0xFFf1e4e8),
body: Stack(
children: [
Container(
padding: EdgeInsets.only(bottom: 125),
child: StreamBuilder(
stream: userBloc.chat(widget.chatID),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else if(snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
return ListView.builder(
controller: scrollController,
physics: BouncingScrollPhysics(),
itemCount: snapshot.data.size,
itemBuilder: (context, index) {
return ChatMessage(
isUserMessage: isUserMessage(snapshot,index),
message:
snapshot.data.docs[index].data()['Message'],
timeStamp:snapshot.data.docs[index].data()['Timestamp']);
},
);
}
}),
);
What is the correct way to do it?
Upvotes: 0
Views: 1889
Reputation: 1220
Attach addListener to your scrollcontroller and then use jumpTo function accordingly. You can follow this example
ScrollController _scrollController;
double _lastEndOfScroll = 0;
_scrollController.addListener(() {
double maxScroll = _scrollController.position.maxScrollExtent;
double currentScroll = _scrollController.position.pixels;
if (maxScroll == currentScroll) {
_lastEndOfScroll = maxScroll;
}
});
_scrollController.jumpTo(_lastEndOfScroll);
Upvotes: 1
Reputation: 390
The simplest solution is the following:
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('<MessagesColection>')
.orderBy('<Time field>',descending: true)
.snapshots(),
builder: (context,snapshot) {
return ListView.builder(
//The reversed list will put the list backwards.
//The start of the list will start at the bottom.
reverse: true,
controller: scrollController,
itemCount: snapshot.data.size,
itemBuilder: (context, index) {
return ChatMessage(snapshot);
},
);
}
),
In the previous code, what was done was to invert the list, the most recent messages will be at the bottom, and order the records in descending order, that is, from the most recent to the least recent. In this way the most recent messages will be at the beginning of the list (in this case at the bottom), and the least at the bottom of the list (in this case at the top).
Upvotes: 0
Reputation: 650
In your initState(), you can register a callback with addPostFrameCallback and it will get called once after the first frame completes rendering. You could use this callback to scroll to the bottom of your ListView.
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback( (_) {
_scrollToBottomOfListView();
}
}
Upvotes: 1