Flutter 聊天屏幕文本输入字段
Flutter Chat Screen Textinputfield
我已经在我的应用程序中创建了聊天。我的问题是,当有人想在 Inputfield 中输入时,Inputfield 由于 phone 键盘而上升,但我的聊天不显示 Inputfield 上方的最后一条消息。有谁知道如何解决这一问题? 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,),),
),
);
}
}
错误的原因是您将 chatMessages
小部件所在的 Container 的固定高度设置为 595 像素。
Container(child: chatMessages(), height: 595),
一个简单的解决方案是计算键盘的高度(参见 this question):
Container(child: chatMessages(), height: MediaQuery.of(context).size.height - 134 - MediaQuery.of(context).viewInsets.bottom),
这需要您设备的实际高度并减去 appBar、textinputfield 和键盘的高度。
但是,使用不依赖于像素计算的小部件树会更有效。特别是带键盘的部分可能会导致在较慢的设备上卡顿。
我已经在我的应用程序中创建了聊天。我的问题是,当有人想在 Inputfield 中输入时,Inputfield 由于 phone 键盘而上升,但我的聊天不显示 Inputfield 上方的最后一条消息。有谁知道如何解决这一问题? 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,),),
),
);
}
}
错误的原因是您将 chatMessages
小部件所在的 Container 的固定高度设置为 595 像素。
Container(child: chatMessages(), height: 595),
一个简单的解决方案是计算键盘的高度(参见 this question):
Container(child: chatMessages(), height: MediaQuery.of(context).size.height - 134 - MediaQuery.of(context).viewInsets.bottom),
这需要您设备的实际高度并减去 appBar、textinputfield 和键盘的高度。
但是,使用不依赖于像素计算的小部件树会更有效。特别是带键盘的部分可能会导致在较慢的设备上卡顿。