I would like to add a section in my app that has a chat view like the most populars chat apps.
I have been searching examples of UI that could meet my need.
I am testing it at first with hard coded messages to check the layout and to test the functionality of the texfield to write the new messages.
Here you have the code and the initial layout screenshot:
class ChatOtroUsuarioMuro extends StatefulWidget {
const ChatOtroUsuarioMuro({Key key, this.usuario, this.otroUsuario})
: super(key: key);
final Usuario usuario;
final OtroUsuario otroUsuario;
@override
_ChatOtroUsuarioMuroState createState() => _ChatOtroUsuarioMuroState();
}
class _ChatOtroUsuarioMuroState extends State<ChatOtroUsuarioMuro> {
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
final mensajes_chat_provider = Provider.of<MensajesChatProvider>(context);
ScrollController _scrollController;
List<ChatMessage> messages = [
ChatMessage(messageContent: "Hello, Will (first message)", messageType: "receiver"),
ChatMessage(messageContent: "How have you been?(second message)", messageType: "receiver"),
ChatMessage(messageContent: "Hey Kriss, I am doing fine dude. wbu?", messageType: "sender"),
ChatMessage(messageContent: "ehhhh, doing OK.", messageType: "receiver"),
ChatMessage(messageContent: "Is there any thing wrong?", messageType: "sender"),
ChatMessage(messageContent: "Hello, Will", messageType: "receiver"),
ChatMessage(messageContent: "How have you been?", messageType: "receiver"),
ChatMessage(messageContent: "Hey Kriss, I am doing fine dude. wbu?", messageType: "sender"),
ChatMessage(messageContent: "ehhhh, doing OK.", messageType: "receiver"),
ChatMessage(messageContent: "Is there any thing wrong?", messageType: "sender"),
ChatMessage(messageContent: "Last message", messageType: "sender"),
];
void scrollToBottom() {
final bottomOffset = _scrollController.position.maxScrollExtent;
_scrollController.animateTo(
bottomOffset,
duration: Duration(milliseconds: 1000),
curve: Curves.easeInOut,
);
}
return Scaffold(
appBar: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
flexibleSpace: SafeArea(
child: Container(
padding: EdgeInsets.only(right: 16),
child: Row(
children: <Widget>[
IconButton(
onPressed: (){
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back,color: Colors.black,),
),
SizedBox(width: 2,),
// CircleAvatar(
// backgroundImage: NetworkImage("<https://randomuser.me/api/portraits/men/5.jpg>"),
// maxRadius: 20,
// ),
SizedBox(width: 12,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Kriss Benwat",style: TextStyle( fontSize: 16 ,fontWeight: FontWeight.w600),),
SizedBox(height: 6,),
Text("Online",style: TextStyle(color: Colors.grey.shade600, fontSize: 13),),
],
),
),
Icon(Icons.settings,color: Colors.black54,),
],
),
),
),
),
body: Stack(
children: <Widget>[
ListView.builder(
itemCount: messages.length,
shrinkWrap: true,
controller: _scrollController,
reverse: true,
padding: EdgeInsets.only(top: 10,bottom: 10),
itemBuilder: (context, index){
return Container(
padding: EdgeInsets.only(left: 14,right: 14,top: 10,bottom: 10),
child: Align(
alignment: (messages[index].messageType == "receiver"?Alignment.topLeft:Alignment.topRight),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: (messages[index].messageType == "receiver"?Colors.grey.shade200:Colors.blue[200]),
),
padding: EdgeInsets.all(10),
child: Text(messages[index].messageContent, style: TextStyle(fontSize: 15),),
),
),
);
},
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
padding: EdgeInsets.only(left: 10,bottom: 10,top: 10),
height: 60,
width: double.infinity,
color: Colors.white,
child: Row(
children: <Widget>[
GestureDetector(
onTap: (){
},
child: Container(
height: 30,
width: 30,
decoration: BoxDecoration(
color: Colors.lightBlue,
borderRadius: BorderRadius.circular(30),
),
child: Icon(Icons.add, color: Colors.white, size: 20, ),
),
),
SizedBox(width: 15,),
Expanded(
child: TextField(
decoration: InputDecoration(
hintText: "Write message...",
hintStyle: TextStyle(color: Colors.black54),
border: InputBorder.none
),
),
),
SizedBox(width: 15,),
FloatingActionButton(
onPressed: (){},
child: Icon(Icons.send,color: Colors.white,size: 18,),
backgroundColor: Colors.blue,
elevation: 0,
),
],
),
),
),
],
),
);
}
}
class ChatMessage{
String messageContent;
String messageType;
ChatMessage({@required this.messageContent, @required this.messageType});
}
As you may see in the screenshot, the first message shown in the list of messages, just above the container with the textfield is not the first message of the list messages, it is the second message. I guess that the first message is hidden behind the container with the textfield.
I have tried to solve the issue, but not solved yet.
What should I take into account to show all messages including the first message?
CodePudding user response:
Perhaps it has something to do with the indexing of your list. Have you tried to add 1 to the index? like so itemCount: messages.length 1,
CodePudding user response:
The reason is that you are using a Stack, which stacks the message input box above the content of the first message. You either need to not use a stack here (for example use a Column) or you need to wrap your ListView in a Container and add margin at the bottom (the same height as the message input box). Like this:
Container(
margin: EdgeInsets.only(bottom: 60),
child: ListView.builder(
itemCount: messages.length,
shrinkWrap: true,
reverse: true,
padding: EdgeInsets.only(top: 10, bottom: 10),
itemBuilder: (context, index) {
return Container(
padding:
EdgeInsets.only(left: 14, right: 14, top: 10, bottom: 10),
child: Align(
alignment: (messages[index].messageType == "receiver"
? Alignment.topLeft
: Alignment.topRight),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: (messages[index].messageType == "receiver"
? Colors.grey.shade200
: Colors.blue[200]),
),
padding: EdgeInsets.all(10),
child: Text(
messages[index].messageContent,
style: TextStyle(fontSize: 15),
),
),
),
);
},
),
),
Here is an example online: https://dartpad.dev/?id=e75b493dae1287757c5e1d77a0dc73f1 (Note that you need to reduce the height of your window if you want to reproduce your original issue).

