1

Here is my code, I want to show my latest send a message at the bottom without getting hidden behind send message container. The whole message list is a listview.builder.

There is a stack, and inside that stack, there are two containers 1 is to show a list of messages, and another is aligned to the bottom is to send messages.

I want that "I want to" message should appear automatically at the bottom, it shouldn't go down.

Here is my code...

I can't find any solution for it yet, did anyone have an answer for this. Thanks for your help.

Stack(
        children: [

          Expanded(
            child: StreamBuilder(
              stream: FirebaseFirestore.instance
                  .collection("Chatroom")
                  .doc(widget.chatRoomId)
                  .collection('chats')
                  .snapshots(),
              builder: (context,
                  AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
                if (snapshot.hasData) {
                  smessageData = snapshot.data!.docs;
                  return Container(
                    margin: EdgeInsets.only(bottom: 60),
                    padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
                    height: MediaQuery.of(context).size.height,
                    color: Colors.black,
                    child: ListView.builder(
                      
                      scrollDirection: Axis.vertical,
                        shrinkWrap: true,
                        itemCount: smessageData.length,
                        itemBuilder: (context, index) {
                          smessageData.sort((a, b) {
                            var adate = a['time'];
                            var bdate = b['time'];
                            return adate.compareTo(bdate);
                          });
                          if (_user!.displayName.toString() ==
                              smessageData[index]['sendBy'].toString()) {
                            align = true;
                          } else {
                            align = false;
                          }
                          return Container(
                            width: MediaQuery.of(context).size.width,
                            alignment: align
                                ? Alignment.centerRight
                                : Alignment.centerLeft,
                            child: Container(
                              margin: EdgeInsets.symmetric(vertical: 10),
                              decoration: BoxDecoration(
                                  color: align ? Colors.blue : Colors.grey,
                                  borderRadius: BorderRadius.only(
                                      bottomLeft: Radius.circular(10),
                                      topLeft: Radius.circular(10),
                                      topRight: Radius.circular(10))),
                              padding: EdgeInsets.symmetric(
                                  horizontal: 10, vertical: 16),
                             

                              child: Text(
                                smessageData[index]['message'].toString(),
                                style: TextStyle(
                                    color: align ? Colors.white : Colors.white),
                              ),
                            ),
                          );
                        }),
                  );
                }
                return Container(
                  child: Text('SOME'),
                );
              },
            ),
          ),
          
          Container(
            alignment: Alignment.bottomCenter,
           
            child: Container(
              color: Colors.grey,
              padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
              child: Row(
                children: [
                  Expanded(
                    child: TextField(

                      controller: messageController,
                      decoration: InputDecoration(
                          border: InputBorder.none,
                          hintText: "Type your Message...",
                          hintStyle:
                          TextStyle(color: Colors.white, fontSize: 20)),
                    ),
                  ),
                  GestureDetector(
                    onTap: () {
                      sendMessage();
                    },
                    child: Container(
                      padding: EdgeInsets.symmetric(horizontal: 5, vertical: 5),
                      decoration: BoxDecoration(
                          shape: BoxShape.circle,
                          gradient: LinearGradient(
                              colors: [Colors.grey, Colors.black54])),

                      child: Icon(
                        Icons.send,
                        size: 20,
                      ),
                    ),
                  )
                ],
              ),
            ),
          ),
        ],
      )

Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
  • Does this answer your question? [Flutter scroll to bottom of Dynamic ListView](https://stackoverflow.com/questions/47916247/flutter-scroll-to-bottom-of-dynamic-listview) – Md. Yeasin Sheikh May 27 '22 at 06:45

4 Answers4

0

You can try by reversed the list of message received from firebase.

List messageList = ['a','b','c','d']; print(messageList.reversed);

  • I want make it as whatsapp, So if i reversed the list new message will appear at TOP of screen, I want, when i click on send the messafe wgich i typed should pushed up. – Tejas Gaikwad May 27 '22 at 07:02
  • Okay, You need to use Scrollcontroller to push your scrollview at the end of the scroll when you send a new message. You can use _myController.jumpTo(_myController.position.maxScrollExtent) OR you can use _scrollController.animateTo( 0.0, curve: Curves.easeOut, duration: const Duration(milliseconds: 300), ); –  May 27 '22 at 07:10
0

A simple way is

smessageData[smessageData.length - 1 - index];

Also, you can implement it with a ScrollController, adding animations, etc

Reg
  • 10,717
  • 6
  • 37
  • 54
0

simple way is

smessageData[smessageData.length - 1 - index];

example

     ListView.separated(
      reverse: true,
      physics: const BouncingScrollPhysics(),
      itemCount: chatModel.length + 1,
      itemBuilder: (context, index) {
        if (index < chatModel.length) {
          final m = chatModel[chatModel.length - 1 - index]; // this
          return MessageWidget(
            imagesModel: m.images,
            name: m.account?.firstName ?? "",
            pathAvatar: m.account?.photo.small ?? "",
            time: DateTimeHelper.timeformatter(
                m.insertedAt ?? DateTime.now()),
            message: m.text,
            isFirstElement: index == 0,
          );
        }
        return const SizedBox();
      },
      separatorBuilder: (context, index) {

also you can implement with ScrollController

like this

 Timer(const Duration(milliseconds: 100), () {
      scrollController.animateTo(
        scrollController.position.maxScrollExtent,
        duration: const Duration(milliseconds: 100),
        curve: Curves.easeInQuad,
      );
    });
0
final ScrollController controller = ScrollController();

Declare a controller in your widget and assign it to the controller property of the listview

Inside the list view, builder property write the below code:

SchedulerBinding.instance.addPostFrameCallback((_)
{
    controller.jumpTo(controller.position.maxScrollExtent);
}