이번에는 채팅 화면을 좀 더 실제처럼 스타일을 적용해 보겠습니다.
개발환경 : 윈도우11, 안드로이드 스튜디오, flutter 3.0.1
화면 구현은 아래와 같습니다.
./src/screens/chat/chat.dart - 채팅 말풍성 위젯
import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../../models/chat_model.dart';
const roundedCorner = Radius.circular(20);
class Chat extends StatelessWidget {
final Size size;
final bool isMine;
final ChatModel2 chatModel;
const Chat(
{Key? key,
required this.size,
required this.isMine,
required this.chatModel})
: super(key: key);
@override
Widget build(BuildContext context) {
return isMine ? _buildMyMsg(context) : _buildOthersMsg(context);
}
// 내 메시지 표시
Widget _buildMyMsg(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(DateFormat('HH:mm').format(chatModel.createdDate)),
const SizedBox(
width: 8,
),
Container(
child: Text(
chatModel.msg,
style: Theme.of(context).textTheme.bodyText1!
.copyWith(color: Colors.white),
),
// 발품선의 여백 설정
padding: const EdgeInsets.symmetric(
vertical: 12,
horizontal: 16,
),
// 말풍선의 최소 높이 40, 화면 폭의 60% 사이즈,
constraints: BoxConstraints(
minHeight: 40,
maxWidth: size.width * 0.6,
),
decoration: const BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.only(
topLeft: roundedCorner,
topRight: Radius.circular(2),
bottomRight: roundedCorner,
bottomLeft: roundedCorner,
),
),
),
],
);
}
// 상대방 메시지 표시
Widget _buildOthersMsg(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ExtendedImage.network(
'https://randomuser.me/api/portraits/women/26.jpg',
width: 36,
height: 36,
fit: BoxFit.cover,
borderRadius: BorderRadius.circular(10),
shape: BoxShape.rectangle,
),
const SizedBox(width: 8),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
child: Text(
chatModel.msg,
style: Theme.of(context).textTheme.bodyText1!
.copyWith(color: Colors.white),
),
padding: const EdgeInsets.symmetric(
vertical: 12,
horizontal: 16,
),
constraints: BoxConstraints(
minHeight: 40,
maxWidth: size.width * 0.55,
),
decoration: BoxDecoration(
color: Colors.grey[300]!,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(2),
topRight: roundedCorner,
bottomRight: roundedCorner,
bottomLeft: roundedCorner,
),
),
),
const SizedBox(width: 8),
Text(DateFormat('HH:mm').format(chatModel.createdDate)),
],
),
],
);
}
}
./src/screens/chat/chatroom_screen.dart - 말풍선 스타일 호출 및 일자 구분용 디바이더 추가
Widget build(BuildContext context) {
// logger.d('${Get.parameters['chatroomKey']}');
Size _size = MediaQuery.of(context).size;
UserModel1 userModel = UserController.to.userModel.value!;
List<ChatModel2> _chatList = ChatController.to.chatList;
Rxn<ChatroomModel2> chatroomModel = ChatController.to.chatroomModel;
return Scaffold(
appBar: AppBar(),
backgroundColor: Colors.grey[200],
// 화면 하단의 메뉴바 때문에 SafeArea 로 wrapping 해야 오동작을 방지함.
body: SafeArea(
child: Column(
children: [
// 게시글 정보를 간략히 표시
_buildItemInfo(context),
// 채팅 메시지 표시 부분
Expanded(
child: Obx(
() => Container(
// color: Colors.yellowAccent,
child: ListView.separated(
shrinkWrap: true,
// 최신 메시지가 아래에 위치하게 설정,
reverse: true,
padding: const EdgeInsets.all(16),
itemBuilder: (context, index) {
bool _isMine = _chatList[index].userKey == userModel.userKey;
// 말풍선 호출
return Chat(
size: _size,
isMine: _isMine,
chatModel: _chatList[index], //chatNotifier.chatList[index],
);
},
separatorBuilder: (context, index) {
// 일자 구분용 디바이더 추가
if (DateFormat('yyyy-MM-dd').format(_chatList[index].createdDate) ==
DateFormat('yyyy-MM-dd').format(_chatList[index + 1].createdDate)) {
return const SizedBox(height: 12);
} else {
return Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
DateFormat('yyyy-MM-dd').format(_chatList[index].createdDate),
),
),
);
}
},
itemCount: _chatList.length, //chatNotifier.chatList.length,
),
),
),
),
const Padding(padding: EdgeInsets.all(4)),
// 메시지 입력 창
_buildInputBar(userModel)
],
),
),
);
}
'Flutter > 12 Clone 'Used Goods app'' 카테고리의 다른 글
[Flutter] Clone - 당근마켓53(Chat - 5) 동시 채팅 및 실제 정보 매핑 (0) | 2022.09.08 |
---|---|
[Flutter] Clone - 당근마켓51(Chat - 3) 메시지 표시 (0) | 2022.09.06 |
[Flutter] Clone - 당근마켓50(Chat - 2) 상단/하단 정보 표시 (0) | 2022.09.02 |
[Flutter] Clone - 당근마켓49(Chat - 1) (1) | 2022.09.01 |
[Flutter] Clone - 당근마켓48(chatroomModel, chatModel) (0) | 2022.08.31 |