[TIL-025] Flutter 위젯 파헤치기 - TextField

`TextField`위젯은 웹에서는 `input`으로 불린다.

 입력 값이라는 뜻이다.

 

애플리케이션에서 사용자와 가장 많은 상호작용을 하는 것 중에 하나가 바로 `TextField`위젯일 것이다.

그만큼 많이 중요하고, 매우 매우 중요하다.

 

기본 사용 방법

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

  @override
  State<MyTextFieldTest> createState() => _MyTextFieldTestState();
}

class _MyTextFieldTestState extends State<MyTextFieldTest> {
  TextEditingController controller = TextEditingController();

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        FocusScope.of(context).unfocus();
      },
      child: Scaffold(
        appBar: AppBar(
          title: TextField(
            controller: controller,
            onChanged: (value) {
              print('onChanged : $value');
            },
          ),
        ),
      ),
    );
  }
}
  • `TextField`위젯은 `StatefulWidget`내에서 사용
  •  `TextEditingController controller = TextEditingController();`를 사용하여 어떤 위젯에서든 입력 값을 가져올 수 있다.
    • `TextEditingController()`를 사용하기 위해 `TextField`위젯의 `controller`속성을 사용
  • ✅ `GestureDetector`위젯의 `onTap`속성 내에서 `FocusScope.of(context).unfocus();`을 사용해야 한다.
    • ✅ `Material`은 키보드가 나타난 후 화면을 탭하면 키보드가 사라지지 않기에 필수로 사용해야 한다.
  • `@override
       void dispose() {
         super.dispose();
         controller.dispose();
       }` 를 사용
    • ✅ `TextEditingController();`를 사용 시, `void dispose`를 오버라이딩하여 `TextField`를 사용하는 페이지가 사라질 때 상태 구독을 중지시켜 메모리에서 삭제하도록 한다.
    • `dispose`를 하기 위해 `StatefulWidget`을 사용하는 것(`StatelessWidget`은 사용 불가)

 

자주 사용하는 속성

`TextField`위젯은 속성이 너무나 많으니 자주 사용하는 것 위주로 먼저 익히는게 좋을 것 같다.

TextField(
    // TextField의 값을 변경하거나, 값을 다른 위젯에서 사용하고 싶을 때!
    controller: controller,

    // TextField의 스타일 설정
    decoration: InputDecoration(
      hintText: "검색어를 입력해 주세요",

      // WidgetStateInputBorder.resolveWith :
      // TextField 상태에 따라 다른 테두리 적용하고 싶을 때!
      border: WidgetStateInputBorder.resolveWith((states) {
        // 포커스일 때
        if (states.contains(WidgetState.focused)) {
          return OutlineInputBorder(
            borderRadius: BorderRadius.circular(10),
            borderSide: BorderSide(color: Colors.redAccent),
          );
        }

        // 기본
        return OutlineInputBorder(
          borderRadius: BorderRadius.circular(10),
          borderSide: BorderSide(color: Colors.grey),
        );
      }),
    ),

    // 모바일에서 키보드 유형 설정 - 숫자 키패드, 문자 등
    keyboardType: TextInputType.text,

    // 키보드의 엔터 버튼의 텍스트를 '완료'로 설정
    textInputAction: TextInputAction.done,

    // 텍스트 변경 시 호출되는 함수
    onChanged: (text) {
      print('Text changed: $text');
    },

    // 키보드에서 엔터 눌렀을 때 호출되는 함수
    onSubmitted: (text) {
      print('Submitted text: $text');
    },

    // true로 설정하면 입력한 텍스트가 가려짐 (비밀번호 입력 시 사용)
    obscureText: false,

    // 최대 글자 수 제한
    maxLength: 50,

    // 최대 입력 줄 수 제한
    maxLines: 1,

    // TextField 글자 스타일
    style: TextStyle(fontSize: 16, color: Colors.black), // 입력 텍스트 스타일
  );
}

 

높이 조절 방법

`TextField`의 높이는 속성을 변경하여 부모의 높이를 그대로 받아와야 높이가 적용된다.

SizedBox(
  height: 200,
  child: TextField(
    textInputAction: TextInputAction.newline,
    expands: true,
    maxLines: null,
    decoration: InputDecoration(hintText: '할 일을 적어주세요'),
  ),
),
  • 부모를 만들어 높이를 설정한다.
  • `textInputAction: TextInputAction.newline` : 키보드의 엔터 버튼을 누르면 개행이 된다.
  • `expands: true` : 이게 있어야 부모의 높이대로 확장이 된다.
  • `maxLines: null` : 타입이 `int?`라서 기본 값이 1이다. `null`로 해줘야 확장이 된다.