일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Django REST
- 프로그래머스
- RxJava
- dart
- 알고리즘
- Android P
- Kotlin
- livedata
- Python
- 안드로이드 구글맵
- C/C++
- 코틀린
- Django REST Android
- Django REST framework
- Android
- NDK
- Flutter TextField
- 안드로이드
- FLUTTER
- C
- C++
- UWP
- android push
- kodility
- mfc
- flutter firestore
- RxAndroid
- Java
- android architecture component
- Rxjava2
- Today
- Total
개발하는 두더지
Flutter - 채팅방 구현하기 본문
코드를 먼저 살펴보면 아래와 같습니다.
하단에 대화를 입력할 수 있는 TextField와 send 버튼이 있고, send 버튼을 누르면 리스트에 텍스트 내용이 하나씩 저장되는 구조입니다.
하나의 채팅 메시지를 나타내는 위젯이 필요합니다. 아래와 같이 ChatMessage
라는 StatelessWidget
을 만들어줍니다.
메시지를 보낸 사용자를 나타내는 간단한 그래픽 아바타, 보낸 사람 이름이 들어있는 Column
위젯 및 메시지 텍스트를 표시하는 Row
위젯을 리턴합니다.
CircleAvatar
위젯을 커스텀하기 위해서 _name 변수 값의 첫 번째 문자를 텍스트 위젯에 전달하여 사용자의 첫 번째 이니셜로 레이블을 지정합니다. CrossAxisAlignment.start
를 row 생성자의 crossAxisAlignment
인수로 사용하여 아바타와 메시지를 상위 위젯에 상대적으로 배치 합니다.
아바타의 경우, 부모는 기본 축이 수평인 row
위젯이므로 CrossAxisAlignment.start
는 수직 축을 따라 가장 높은 위치를 제공합니다. 메시지의 경우 부모는 세로 축인 Column
위젯이므로 CrossAxisAlignment.start
는 가로 축을 따라 가장 왼쪽에있는 텍스트를 정렬합니다.
아바타 옆에 두 개의 텍스트 위젯을 세로로 정렬하여 보낸 사람의 이름을 맨 위에 표시하고 텍스트의 텍스트를 아래에 표시합니다. 보낸 사람의 이름을 스타일링하고 메시지 텍스트보다 크게 만들려면 Theme.of
를 사용하여 적절한 ThemeData
객체를 가져와야합니다.
textTheme
속성을 사용하면 부제목과 같은 텍스트의 Material design logical styles에 액세스 할 수 있으므로 글꼴 크기 및 기타 텍스트 속성을 하드 코딩하지 않아도됩니다.
다음 단계는 채팅 메시지 목록을 가져 와서 UI에 표시하는 것입니다. 사용자가 채팅 기록을 볼 수 있도록 목록을 스크롤 할 수 있어야 합니다. 또한 목록은 가장 최근 메시지가 맨 아래 행에 표시되도록 해야합니다.
우선 List
컬렉션을 이용하여 채팅 메시지를 저장할 자료구조를 선언합니다. 그리고 전송 버튼을 눌러 _handleSubmitted
가 호출될 때 ChatMessage 객체를 만들어 setState
메서드를 통해 _messages
를 수정하고 위젯 트리가 변경되었음을 프레임 워크가 알 수 있도록 UI를 다시 작성해야합니다. setState
에서는 동기 작업 만 수행해야합니다. 그렇지 않으면 프레임 워크가 작업을 완료하기 전에 위젯을 다시 그릴 가능성이 있습니다.
import 'package:flutter/material.dart';
void main() => runApp(FriendlychatApp());
const String _name = "Your Name";
class FriendlychatApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "FriendlychatApp",
home: ChatScreen(),
);
}
}
class ChatScreen extends StatefulWidget {
@override
State createState() => ChatScreenState();
}
class ChatScreenState extends State<ChatScreen> {
final List<ChatMessage> _messages = <ChatMessage>[];
final TextEditingController _textController = new TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Friendlychat"),
),
body: Column(
children: <Widget>[
Flexible(
child: ListView.builder(
padding: EdgeInsets.all(8.0),
reverse: true,
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
),
),
Divider(height: 1.0),
Container(
decoration: BoxDecoration(
color: Theme.of(context).cardColor
),
child: _buildTextComposer(),
)
],
),
);
}
Widget _buildTextComposer() {
return IconTheme(
data: IconThemeData(color: Theme.of(context).accentColor),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
children: <Widget>[
Flexible(
child: TextField(
controller: _textController,
onSubmitted: _handleSubmitted,
decoration: new InputDecoration.collapsed(
hintText: "Send a message"),
),
),
Container(
margin: const EdgeInsets.symmetric(horizontal: 4.0),
child: IconButton(
icon: Icon(Icons.send),
onPressed: () => _handleSubmitted(_textController.text)),
),
],
)
),
);
}
void _handleSubmitted(String text) {
_textController.clear();
var message = ChatMessage(
text: text,
);
setState(() {
_messages.insert(0, message);
});
}
}
class ChatMessage extends StatelessWidget {
ChatMessage({this.text});
final String text;
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: const EdgeInsets.only(right: 16.0),
child: CircleAvatar(child: Text(_name[0])),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(_name, style: Theme.of(context).textTheme.subhead),
Container(
margin: const EdgeInsets.only(top: 5.0),
child: Text(text),
),
],
),
],
),
);
}
}
'Flutter' 카테고리의 다른 글
Flutter - Firestore 라이브러리 사용하기 (2) (0) | 2019.04.26 |
---|---|
Flutter - Firestore 라이브러리 사용하기 (1) (0) | 2019.04.26 |
Flutter - TextField, Send 버튼 만들기 (0) | 2019.04.23 |
Flutter - 무한 스크롤링 리스트뷰 만들기 (0) | 2019.04.21 |
Flutter - StatefulWidget 이란? (1) | 2019.04.21 |