개발하는 두더지

Flutter - TextField, Send 버튼 만들기 본문

Flutter

Flutter - TextField, Send 버튼 만들기

덜지 2019. 4. 23. 00:06

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를 메서드에 명시적으로 전달할 필요가 없습니다.

Comments