HyunJun 기술 블로그

TextField, TextFormField, Form 본문

Flutter

TextField, TextFormField, Form

공부 좋아 2023. 7. 25. 09:23
728x90
반응형

Flutter에서의 사용자 입력받기.

Flutter에서 사용자가 직접 입력한 텍스트를 받고 유효성 검사 등을 하기 위해서 TextField, TextFormField, Form 등이 사용된다.

 

1) TextField

Flutter에서 name, id, email, pw 등 사용자의 입력을 받기 위해 사용한다. TextField 위젯은 단순히 텍스트를 입력을 받기 위한 위젯으로, 폼 처리나 유효성 검사를 위한 기능을 내장하고 있지 않다. 하여 Form 위젯 안에 위치할 필요가 없고 단독으로 사용 가능하다.

  • controller: 사용자가 TextField에 입력한 값을 저장하고 재 사용 및 관리하기 위해 TextEditingController를 사용한다.
  • decoration: TextField의 외관을 설정할 수 있는 InputDecoration. (선택사항)
  • enabled: 입력 필드의 활성화 여부를 결정하는 bool 값. (기본값: true)
  • autofocus: 위젯이 화면에 나타날 때 자동으로 포커스를 받을지 여부를 결정하는 bool 값. (기본값: false)
  • keyboardType: 입력 필드에 표시할 키보드 유형을 결정하는 TextInputType 값. (기본값: TextInputType.text)
  • inputFormatters: 입력 필드에 적용할 텍스트 포맷터 리스트. (선택사항)
  • onChanged: 입력 필드의 텍스트가 변경될 때 호출되는 콜백 함수. (선택사항)
  • onEditingComplete: 사용자가 편집을 완료했을 때 호출되는 콜백 함수. (선택사항)
  • onSubmitted: 사용자가 엔터 키를 눌렀을 때 호출되는 콜백 함수. (선택사항)
  • maxLength: 입력 가능한 최대 문자 길이를 제한하는 int 값. (선택사항)
  • maxLines: 입력 필드의 최대 행 수를 결정하는 int 값. (기본값: 1)
  • minLines: 입력 필드의 최소 행 수를 결정하는 int 값. (기본값: 1)
  • obscureText: 비밀번호와 같이 텍스트를 가려서 표시할지 여부를 결정하는 bool 값. (기본값: false)
  • textAlign: 텍스트의 정렬 방향을 결정하는 TextAlign 값. (기본값: TextAlign.start)
  • textCapitalization: 입력된 텍스트의 대문자 변환 방식을 결정하는 TextCapitalization 값. (기본값: TextCapitalization.none)

 

 

StatefulWidget으로 기본 위젯을 만든다.

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

 

TextField에 입력한 값을 관리하기 위해 TextEditingController를 선언한다.

class _HomeScreenState extends State<HomeScreen> {
  TextEditingController _idController = TextEditingController();
  TextEditingController _pwController = TextEditingController();
  
  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

 

 

build 메서드를 아래와 같이 수정한다. TextField에 controller를 지정해 주고, obscureText를 통해 입력값을 점으로 표시한다.(비밀번호 입력) Submit 버튼 클릭 시 컨트롤러를 통해 해당 TextField의 Text를 가지고 와 보여준다.

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Column(
          children: [
            TextField(
              controller: _idController,
              decoration: InputDecoration(labelText: "id 입력"),
            ),
            TextField(
              obscureText: true,
              controller: _pwController,
              decoration: InputDecoration(labelText: "pw 입력"),
            ),
            ElevatedButton(
                onPressed: () {
                  String id = _idController.text;
                  String pw = _pwController.text;

                  showDialog(
                    context: context,
                    builder: (context) {
                      return AlertDialog(
                        title: Text("id: ${id} \npw: ${pw}"),
                        actions: [
                          TextButton(
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                              child: Text('OK'))
                        ],
                      );
                    },
                  );
                },
                child: Text("Submit"))
          ],
        ),
      ),
    );
  }

 

 

2) onSubmitted, onEditingComplete

기본적으로 onSubmitted와 onEditingComplete는 해당 TextField에서 모바일 키보드에서 done 등을 터치하면 동작한다. 즉 해당 텍스트 필드에 대해서 입력이 완료되었을 때 동작한다는 개념은 같다. 이때 기본적으로 텍스트 필드 입력 완료 후의 기본 동작은 해당 TextField에서 focus를 잃고 모바일 키보드가 내려가게 된다.(기본 done 동작)

 

이때 onEditingComplete를 선언해 주게 되면 기본 TextField done 동작과는 다르게 focus를 유지하며, done 동작 후에도 키보드를 유지할 수 있다. 즉, onEditingComplete 시 포커스를 잃고, 키보드가 내려가는 기본값을 없애는 것이다.

  onEditingComplete: (){
    print("onEditingComplete");
  },

 

3) Form과 TextFormField

폼을 설정하고, 유효성 검증을 쉽게 하고, TextField보다 여러 가지 확장된 기능을 사용하려면 Form과 TextFormFeild 위젯을 사용해야 한다.

 

  • Form의 상태를 관리하는 GlobalKey<FormState>를 선언하고 Form에 등록하여 사용할 수 있다.
  • 각각의 TextFormField에서 validator를 활용해서 입력값 value에 대한 유효성 검사를 진행할 수 있다.
    • 이때 유효성 검증에 실패하면 해당 return "", String 값이 빨간 글자로 띄워주게 되며,
    • return 값이 null인 경우를 유효성 검증에 통과했다고 본다.
  • .currentState!.validate()를 통해 Form 내에 있는 TextFormField 들의 유효성 검증이 통과했는지를 true, false로 넘겨받는다.
  • .currentState!.save();를 사용하게 되면, 각각의 TextFormField에 있는 onSaved가 동작하게 된다.

즉, 각각의 입력값에 대한 유효성 검증 통과 시 -> 각각의 입력값에 대한 onSaved 콜백 함수를 실행할 수 있는 것이다.

import 'package:flutter/material.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final _formKey = GlobalKey<FormState>(); // GlobalKey for Form

  String _idValue = "";
  String _pwValue = "";

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Form(
          key: _formKey, // Assign the GlobalKey to Form
          child: Column(
            children: [
              TextFormField(
                decoration: InputDecoration(labelText: "id 입력", hintText: "id"),
                validator: (value) {
                  if (value!.isEmpty) {
                    return '아이디를 입력해주세요.';
                  }
                  return null;
                },
                onSaved: (value) {
                  _idValue = value!;
                },
              ),
              TextFormField(
                obscureText: true,
                decoration: InputDecoration(labelText: "pw 입력", hintText: "pw"),
                validator: (value) {
                  if (value!.isEmpty) {
                    return '비밀번호를 입력해주세요.';
                  }
                  return null;
                },
                onSaved: (value) {
                  _pwValue = value!;
                },
              ),
              ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    _formKey.currentState!.save();

                    showDialog(
                      context: context,
                      builder: (context) {
                        return AlertDialog(
                          title: Text("id: ${_idValue} \npw: ${_pwValue}"),
                          actions: [
                            TextButton(
                              onPressed: () {
                                Navigator.of(context).pop();
                              },
                              child: Text('OK'),
                            ),
                          ],
                        );
                      },
                    );
                  }
                },
                child: Text("Submit"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

 

그 외에, CupertinoTextField, Slider, Switch, Radio, DropdownButton, DatePicker, TimePicker, Checkbox 등을 활용하여 여러 가지 종류의 입력값을 받을 수 있다.

728x90
반응형
Comments