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,),),
),
);
}
}
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.