Search code examples
databaseflutterlistviewchat

Flutter Chat Screen Textinputfield


I have create a Chat in my app. My problem is that when someone want to type in the Inputfield the Inputfield goes up because of the phone keyboard but my chat dont show the last message above the Inputfield. Does anyone know how to fix this? Chatscreen and Chatscreen with keyboard

class Chat extends StatefulWidget {
  final String chatRoomId;

  Chat({this.chatRoomId});




  @override
  _ChatState createState() => _ChatState();
}

class _ChatState extends State<Chat> {

  Stream<QuerySnapshot> chats;
  TextEditingController messageEditingController = new TextEditingController();
  Stream chatRooms;





  Widget chatMessages(){
    return StreamBuilder(
      stream: chats,
      builder: (context, snapshot){
        return snapshot.hasData ?
            ListView.builder(
                itemCount: snapshot.data.docs.length,
                itemBuilder: (context, index){
                  return MessageTile(
                    message: snapshot.data.docs[index].data()["message"],
                    sendByMe: Constants.myName == snapshot.data.docs[index].data()["sendBy"],
                    time: snapshot.data.docs[index].data()["time"],
                  );
                },
        ) : SpinKitFadingCircle(color: Colors.white, size: 20.0);
      },
    );
  }





  addMessage() {
    if (messageEditingController.text.isNotEmpty) {
      Map<String, dynamic> chatMessageMap = {
        "sendBy": Constants.myName,
        "message": messageEditingController.text,
        'time': DateTime
            .now()
            .millisecondsSinceEpoch,
      };

      DatabaseService().addMessage(widget.chatRoomId, chatMessageMap);

      setState(() {
        messageEditingController.text = "";
      });
    }
  }

  @override
  void initState() {
    DatabaseService().getChats(widget.chatRoomId).then((val) {
      setState(() {
        chats = val;
      });
    });
    super.initState();
  }

  Future<DocumentSnapshot> getUserInfo() async {
    var firebaseUser = await FirebaseAuth.instance.currentUser;
    return await FirebaseFirestore.instance.collection("SerX")
        .doc(firebaseUser.uid)
        .get();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        backgroundColor: Colors.black,
        bottom: PreferredSize(
            child: Container(
              color: Colors.blue,
              height: 4.0,
            ),
            preferredSize: Size.fromHeight(0)),
        title:Text("Conversation",
          style: TextStyle(
              color: Colors.white,
              fontFamily: 'Orbitron',
              fontSize: 20.0,
              fontWeight: FontWeight.bold,
              letterSpacing: 2.2
          ),),
        leading: IconButton(icon: Icon(Icons.arrow_back ,color: Colors.blue,),onPressed: (){
          Navigator.pushReplacement(context,
              MaterialPageRoute(builder: (context) => Search()));
        },),
      ),

      body: Container(
        child: Stack(
          children: [
            Container(child: chatMessages(), height: 595),
            Container(
              alignment: Alignment.bottomCenter,
              child: Container(
                padding: EdgeInsets.symmetric(horizontal: 25, vertical: 3),
                color: Colors.white,
                child: Row(
                  children: [
                    Expanded(
                      child: TextField(
                        controller: messageEditingController,
                        style: TextStyle(
                          color: Colors.white,
                          fontFamily: 'Orbitron',
                          fontSize: 12.0,
                          fontWeight: FontWeight.bold,
                        ),
                        decoration: InputDecoration(
                          contentPadding: new EdgeInsets.symmetric(vertical: 7, horizontal: 15),
                          filled: true,
                          fillColor: Colors.black,
                          enabledBorder: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(40),
                              borderSide: BorderSide(color: Colors.blue, width: 3)
                          ),
                          focusedBorder: OutlineInputBorder(
                              borderRadius: BorderRadius.circular(40),
                              borderSide: BorderSide(color: Colors.blue, width: 3,)
                          ),
                          border: InputBorder.none,
                        ),
                      ),
                    ),
                    SizedBox(width: 20,),
                    GestureDetector(
                      onTap: () {
                        addMessage();
                      },
                      /*
                      child:Container(
                        height: 45,
                        width: 45,
                        decoration: BoxDecoration(
                            gradient: LinearGradient(
                                colors: [
                                  const Color(0xFF000000),
                                  const Color(0xFF000000),
                                ]
                            ),
                            borderRadius: BorderRadius.circular(40),
                            border: Border.all(
                                width: 2,
                                color: Colors.blue
                            )
                        ),

                       */
                          child:Icon(Icons.send, color: Colors                      ///  <--- Um den grauen script zu aktivieren hinter Icon eine klammer zu setzen!
                              .black, size: 35,),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

}

class MessageTile extends StatelessWidget {
  final String message;
  final bool sendByMe;
  final int time;

  MessageTile({@required this.message, @required this.sendByMe, @required this.time});


  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.only(
          top: 3,
          bottom: 3,
          left: sendByMe ? 0 : 24,
          right: sendByMe ? 24 : 0),
      alignment: sendByMe ? Alignment.centerRight : Alignment.centerLeft,
      child: Container(
        margin: sendByMe
            ? EdgeInsets.only(left: 30)
            : EdgeInsets.only(right: 30),
        padding: EdgeInsets.only(
            top: 17, bottom: 17, left: 20, right: 20),
        decoration: BoxDecoration(
            borderRadius: sendByMe ? BorderRadius.only(
                topLeft: Radius.circular(9),
                topRight: Radius.circular(9),
                bottomLeft: Radius.circular(9),
            ) :
            BorderRadius.only(
                topLeft: Radius.circular(9),
                topRight: Radius.circular(9),
                bottomRight: Radius.circular(9)),
           color: sendByMe ? Colors.blue : Colors.white
        ),
        child: Text(message,
            textAlign: TextAlign.start,
            style: TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.bold,
    fontFamily: 'Orbitron',
    fontSize: 9.0,),),
      ),
    );
  }
}


Solution

  • The cause of the error is that you set 595 pixels as a fixed height for the Container your chatMessages widget is in.

    Container(child: chatMessages(), height: 595),

    An easy solution would be to calculate the height of the keyboard (see this question):

    Container(child: chatMessages(), height: MediaQuery.of(context).size.height - 134 - MediaQuery.of(context).viewInsets.bottom),

    This takes the actual height of your device and subtracts the height of appBar, textinputfield and keyboard.

    However, it would be more efficient to use a widget tree that does not depend on pixel calculations. Especially the part with the keyboard may lead to lagging on slower devices.