Flutter - TextField, Send 버튼 만들기
Flutter framework에는 TextField
라 불리는 상태 기반 위젯이 있습니다. 입력 필드의 동작을 커스텀하는 속성을 가진 상태 기반 위젯입니다. State
란 위젯이 빌드되고 위젯 생명주기 동안 변경될 때 동기적으로 읽을 수 있는 정보입니다.
위젯에 상태기반 데이터를 표시하기 위해서는 데이터를 State
object에 캡슐화해야 합니다. 그런 다음 State 객체를 StatefulWidget
클래스를 확장한 위젯과 연결할 수 있습니다.
import 'package:flutter/material.dart';
void main() => runApp(FriendlychatApp());
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> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Friendlychat"),
),
);
}
}
TextField와 상호작용하려면 TextEditingController
를 사용하는 것이 유용합니다. input field로부터 텍스트을 읽고, 텍스트를 전송한 뒤에 clear하는데 사용됩니다.
디바이스 스크린의 모서리와 input field의 각 사이드 사이에 수평 margin을 추가하는 Container
위젯을 추가해줍니다.
여기에 사용되는 값은 iOS의 경우 points
, Android의 경우 dp
에 해당합니다.
텍스트 필드의 내용을 제어하기 위해 TextField
생성자에 TextEditingController
를 제공합니다. 이 컨트롤러는 필드를 지우거나 값을 읽을 때도 사용할 수 있습니다.
유저가 메시지를 보낸 것을 받기 위한 callback으로 onSubmitted
메서드를 구현해줍니다. 전송버튼을 클릭하면 값을 clear 해줍니다.
class ChatScreenState extends State<ChatScreen> {
final TextEditingController _textController = new TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Friendlychat"),
),
body: _buildTextComposer(),
);
}
Widget _buildTextComposer() {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
child: TextField(
controller: _textController,
onSubmitted: _handleSubmitted,
decoration: new InputDecoration.collapsed(
hintText: "Send a message"),
),
);
}
void _handleSubmitted(String text) {
_textController.clear();
}
}
이제 textfield 오른쪽에 전송버튼을 만들어보겠습니다. 입력 필드 옆에 버튼을 표시하고자하므로 row
위젯을 부모로 사용합니다.
그런 다음 TextField
위젯을 Flexible
위젯으로 감싸줍니다. 이렇게하면 버튼이 사용하지 않는 나머지 공간을 사용하도록 텍스트 필드의 크기를 자동으로 지정합니다.
이제 send 아이콘을 표시하는 IconButton
위젯을 만들어 줍니다.
icon
속성에서 Icons.send
상수를 사용하여 새 Icon
인스턴스를 만듭니다. 이 상수는 위젯이 머티리얼 아이콘 라이브러리에서 제공하는 다음 send
아이콘을 사용함을 나타냅니다.
다른 Container
위젯 안에 IconButton
위젯을 넣으십시오. 이렇게하면 버튼의 여백 간격을 사용자 정의 할 수 있으므로 입력 필드 옆에 시각적으로 잘 맞게됩니다. onPressed
속성의 경우 익명 함수를 사용하여 _handleSubmitted
메서드를 호출하고 _textController
를 사용하여 메시지 내용을 전달합니다.
Widget _buildTextComposer() {
return 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)),
),
],
)
);
}
여기까지 진행하면 send 버튼이 검은색으로 나오게됩니다.
앱의 아이콘에 강조 색상을 지정하려면 IconButton에 color 파라미터를 전달합니다. 또는 다른 테마를 적용 할 수 있습니다.
아이콘은 IconThemeData
객체를 사용하여 이러한 특성을 정의하는 IconTheme
위젯에서 색상, 불투명도 및 크기를 상속받습니다. IconTheme
위젯의 _buildTextComposer
메소드에있는 모든 위젯을 래핑하고 data
속성을 사용하여 현재 테마의 ThemeData
객체를 지정합니다. 이렇게하면 버튼에 현재 테마의 강조 색상이 표시됩니다.
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)),
),
],
)
),
);
}
BuildContext
객체는 앱 위젯 트리에서 위젯의 위치에 대한 핸들입니다.
각 위젯에는 StatelessWidget.build
또는 State.build
함수에서 반환 된 자체 BuildContext
가 있습니다. 즉, _buildTextComposer
메서드는 해당 State
객체를 캡슐화하여 BuildContext
객체에 액세스 할 수 있습니다. Context
를 메서드에 명시적으로 전달할 필요가 없습니다.