how to do firebase real time Animated List set scroll controller when new chat message added?

21 views Asked by At

I try to implement fetch the data from firebase real time database by firebase Animated List. it's fetch the data correctly by insetting only query No need to other function and sorting but when add chat Message in to the list or fetch the data not scrolling to end to the bottom like other chat app like what's app and telegram. and i use flutter dart android studio firebase_auth: ^4.16.0 firebase_database: ^10.4.0 firebase_core: ^2.24.2 firebase_storage: ^11.6.0 cloud_firestore: ^4.14.0 I use letest of this version. the AnimatedList it receive controller but i try so many thing Not work please answer me it is important i work lange sacale project in my carryer Here is the ui of my animatedList view on android

  • I Try create scroll controller
  • set value in initState
  • create function for animated list
  • call it in send funciton
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:pasca/assets/custom_colors/colors.dart';
import 'package:pasca/methods/my_methods/shared_pref_method.dart';
import 'package:pasca/wediget/chat_messages_list.dart';
import 'package:pasca/wediget/snack_bar.dart';

import '../../second_code_test.dart';

class ChatRoom extends StatefulWidget {
  String friendId;
  String profileImage;
  String friendName;

  ChatRoom({
    required this.friendId,
    required this.profileImage,
    required this.friendName,
  });

  @override
  State<ChatRoom> createState() => _ChatRoomState();
}

class _ChatRoomState extends State<ChatRoom> {
  final TextEditingController _messageController = TextEditingController();
  final Query _dbRef = FirebaseDatabase.instance.ref().child('Chats');
  String uid = '';
  late ScrollController _scrollController;
  List<Map<String, dynamic>> chatMessageList = [];

  @override
  void initState() {
    super.initState();
    fetchData();
    // Listen for new messages and scroll to the bottom
    _dbRef.onChildAdded.listen((event) {
      _scrollController = ScrollController();
    });
    readMessage();
  }

  void fetchData() async {
    String _uid = await SharedPref().getUid() ?? '';
    // getting my id
    setState(() {
      uid = _uid;
    });
  }
  @override
  void dispose() {
    super.dispose();
    _scrollController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;

    return Scaffold(
      backgroundColor: CustomColors.primaryColor,
      appBar: AppBar(
        backgroundColor: CustomColors.secondaryColor,
        leading: IconButton(
          onPressed: () {
            Navigator.pop(context);
          },
          icon: const Icon(
            Icons.arrow_back,
            color: CustomColors.thirdColor,
          ),
        ),
        title: Row(
          children: [
            CircleAvatar(
              backgroundImage: NetworkImage(
                  widget.profileImage), // get profile from chat list
            ),
            const SizedBox(
              width: 10,
            ),
            Text(
              widget.friendName, // get name from chat list
              style: const TextStyle(
                color: CustomColors.thirdColor,
              ),
            ),
          ],
        ),
      ),
      body: Column(
        children: [
          Expanded(
            child: FirebaseAnimatedList(
              query: _dbRef,
              itemBuilder: (BuildContext context, DataSnapshot snapshot,
                  Animation<double> animation, int index) {
                Map users = snapshot.value as Map;
                // check message sender to my id b/c to put on the right side ot message
                final bool isMe = users['sender'] == uid;
                // check if message send by me or receive by me b/c in chat room display on my massage and friend message
                if (users['sender'] == uid &&
                        users['receiver'] == widget.friendId ||
                    users['sender'] == widget.friendId &&
                        users['receiver'] == uid) {
                  return Align(
                    alignment:
                        isMe ? Alignment.centerRight : Alignment.centerLeft,
                    child: ChatMessageList(
                      // this is list item inside containt if it is me change border, alignment , and color based on bool answer
                      message: users['message'],
                      timeStamp: users['timeStamp'],
                      RBL: isMe ? 20 : 3,
                      RBR: isMe ? 3 : 20,
                      backColor: isMe
                          ? CustomColors.secondaryColor
                          : CustomColors.fourthColor,
                      textColor: isMe
                          ? CustomColors.fourthColor
                          : CustomColors.primaryColor,
                      inSideContaintAlign:
                          isMe ? const Alignment(1, 0) : const Alignment(-1, 0),
                    ),
                  );
                }
                // if no message send me and myfriend it will return null container
                return Container();
              },
            ),
          ),
          Align(
            alignment: Alignment.bottomCenter,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Container(
                  margin: const EdgeInsets.only(
                    right: 10,
                    bottom: 20,
                  ),
                  padding: const EdgeInsets.symmetric(
                    horizontal: 10,
                  ),
                  width: size.width / 1.4,
                  decoration: BoxDecoration(
                    color: CustomColors.secondaryColor,
                    borderRadius: BorderRadius.circular(20),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black.withOpacity(0.3),
                        spreadRadius: 5,
                        blurRadius: 20,
                        offset: const Offset(0, 5),
                      ),
                    ],
                  ),
                  child: TextField(
                    controller: _messageController,
                    style: const TextStyle(
                      color: CustomColors.fourthColor,
                    ),
                    decoration: InputDecoration(
                      border: InputBorder.none,
                      prefixIcon: IconButton(
                        onPressed: () {},
                        icon: const Icon(
                          Icons.photo_camera_outlined,
                          color: CustomColors.thirdColor,
                        ),
                      ),
                      suffixIcon: IconButton(
                        onPressed: () {},
                        icon: const Icon(
                          Icons.keyboard_voice_outlined,
                          color: CustomColors.thirdColor,
                        ),
                      ),
                    ),
                  ),
                ),
                Container(
                  margin: const EdgeInsets.only(bottom: 20),
                  decoration: BoxDecoration(
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black.withOpacity(0.3),
                        spreadRadius: 5,
                        blurRadius: 20,
                        offset: const Offset(0, 5),
                      ),
                    ],
                  ),
                  child: InkWell(
                    onTap: sendMessage,
                    child: const CircleAvatar(
                      backgroundColor: CustomColors.thirdColor,
                      radius: 25,
                      child: Icon(
                        Icons.send_outlined,
                        color: CustomColors.secondaryColor,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  void readMessage() {
    final DatabaseReference dbRef = FirebaseDatabase.instance.ref();

    dbRef.child('Chats').orderByChild('timeStamp').onValue.listen((event) {
      Map<dynamic, dynamic> chatMessage =
          event.snapshot.value as Map<dynamic, dynamic>;
      chatMessageList.clear();
      List<MapEntry<dynamic, dynamic>> entries = chatMessage.entries.toList();

      entries.sort((a, b) {
        // Compare the "timeStamp" values for sorting
        int timeStampA = a.value['timeStamp'];
        int timeStampB = b.value['timeStamp'];
        return timeStampA.compareTo(timeStampB);
      });
      for (int i = 0; i < entries.length; i++) {
        MapEntry<dynamic, dynamic> entry = entries[i];
        Map<String, dynamic> value = Map<String, dynamic>.from(entry.value);
        // get user that sender is me or the message receive to me
        if (value['sender'] == uid && value['receiver'] == widget.friendId ||
            value['sender'] == widget.friendId && value['receiver'] == uid) {
          chatMessageList.add(value);
        }
      }


    }).onError((error) {
      showSnackBar(context, error.toString());
    });
  }

  void sendMessage() async {
    // geting all nessasry info for send message e.g uid, friendId, message,date,database e.t.c .....
    User? user = FirebaseAuth.instance.currentUser;
    String uid = user!.uid;
    String friendId = widget.friendId;
    String message = _messageController.text;
    String myId = await SharedPref().getUid() ?? uid;
    DatabaseReference dbRef = FirebaseDatabase.instance.ref();

    if (message.isNotEmpty && message != ' ' && message != '  ') {
      // chat info map or object
      Map<String, dynamic> chatData = {
        'message': message,
        'sender': myId,
        'receiver': friendId,
        'timeStamp': ServerValue.timestamp,
      };
      // inserting chat data
      dbRef.child('Chats').push().set(chatData).then((_) {
        // handle code when data inserted
        _messageController.text = '';
      }).catchError((error) {
        showSnackBar(context, 'Error inserting data: $error');
      });
    }
    _scrollController;
  }

  void scrollToBottom() {
    _scrollController.animateTo(
      _scrollController.position.maxScrollExtent,
      duration: Duration(milliseconds: 300),
      curve: Curves.easeOut,
    );
  }
}

this is flutter dart code of animated list but i try to send message but not scroll automatically

0

There are 0 answers