키즈_프로젝트

2. 로그인 화면 필수 요소들 - 인풋필드 만들기 ( Controller,FocusNode,initState,dispose )

깡 딱 2024. 10. 26. 20:23
728x90

시작전 요약

 

TextEditingController()
역할: 사용자가 입력한 데이터를 저장하고 관리하는 역할을 합니다.

FocusNode()
역할: 특정 입력 필드에 포커스를 제어하는 역할을 합니다. 즉, 현재 어떤 입력 필드가 활성화되어 있는지를 나타냅니다.

initState()
이유: 위젯이 처음 만들어질 때 한 번만 호출됩니다. 이곳에서 초기 설정을 하거나 리스너를 추가해야 합니다.
예시: 입력 필드에 포커스가 생겼을 때 반응하려면, 이곳에서 리스너를 추가해야 합니다.
dispose()
이유: 위젯이 더 이상 필요하지 않을 때 호출됩니다. 이곳에서 리스너를 제거하고 리소스를 정리합니다.
예시: 포커스 리스너를 제거하여 메모리 누수를 방지하고, 기본 상태로 돌아가게 합니다.

 


컨트롤러

 

이번에 만들 것은

이런 인풋필드입니다.

 

기초 컨트롤러에 대해서 설명하겠습니다.

final _textController = TextEditingController();

먼저 우리가 이메일에 텍스트를 적는데 그걸 저장시킬 친구가 필요한데

그 친구가 TextEditingController() 이 친구입니다. 우리는 이 친구를  _textController라고 부르기로 했어요. (변수)

 

TextEditingController는 클래스이며, TextEditingController()는 그 클래스의 인스턴스를 생성하는 생성자입니다.

 

이제 컨트롤러를 넣을 ui가 필요하겠죠?

TextField, TextFormField 이런 것들이 있는데

 

저는 커스텀이 가능한 TextFormField이 친구를 쓸 거예요

 

TextFormField 안에 저희가 아까 만든 변수를 넣어줍니다. 이렇게 되면 

이 인풋필드 안에 우리가 적은 텍스트들이 바운딩되겠죠?

controller: _textController,

 


포커스

 

근데 우리가 사용자가 눌렀을 때 인풋필드가 변하게 만들고 싶잖아요?

예를 들어 

 

이렇게 빨간색으로 변하거나 파란색으로 사용자가 오류가 났을 때, 사용자가 눌렀을 때 확인을 시켜줘야 되는데

그걸 만들기 위해서 포커스가 중요합니다.

final FocusNode _emailfocusNode = FocusNode();

이런 식으로 이메일 포커스를 만들어줄게요.

 FocusNode
역할: 특정 입력 필드에 포커스를 제어하는 역할을 합니다. 즉, 현재 어떤 입력 필드가 활성화되어 있는지를 나타냅니다

 

 

TextFormField(
                          controller: _textController,
                          focusNode: _emailfocusNode,
                        ),

이런식으로  이제 포커스와 컨트롤러가 들어가게 된다면 준비는 끝났습니다.

 

이제 자기가 원하는 텍스트 스타일과 

style: TextStyle(
  color: Color(0xFF3D3D3D),
  fontSize: 16,
  fontFamily: 'Pretendard',
  fontWeight: FontWeight.w500,
  height: 1.0,
  letterSpacing: -0.4,
),

 

데코레이션을 넣어주고 

 InputDecoration(
    border: InputBorder.none,
    focusedBorder: InputBorder.none,
    contentPadding: EdgeInsets.only(bottom: 10),
    hintText: '이메일입니다.',
    hintStyle: TextStyle(
      color: Color(0xFF888888),
      fontSize: 16,
      fontFamily: 'Pretendard',
      fontWeight: FontWeight.w500,
      height: 1.0,
      letterSpacing: -0.4,
    ),
    suffixIcon: _textController.text.isNotEmpty
        ? IconButton(
        onPressed: () {
          _textController.clear();
          setState(() {});
        },
        padding:
        EdgeInsets.only(bottom: 10, left: 60),
        icon: Icon(Icons.cancel,
            color: Color(0xFF888888)))
        : null),

 

이 부분은 

suffixIcon: _textController.text.isNotEmpty
    ? IconButton(
    onPressed: () {
      _textController.clear();
      setState(() {});
    },
    padding:
    EdgeInsets.only(bottom: 10, left: 60),
    icon: Icon(Icons.cancel,
        color: Color(0xFF888888)))

텍스트가 입력 됐을 때 X아이콘을 눌렀을 때 컨트롤러를 다 지워주는 역할을 하는데

크게 안 넣어도 됩니다.

 

 

Color _emailborderColor = Color(0xFFD1D1D1); // 기본 테두리 색상

이제 컬러 색을 바꾸기 위해서 원래있던 기본 테두리 색상을 정의해두고 변수하나를 만들어줍니다.

 

저는 테두리 부분 색을 바꾸고 싶기 때문에 테두리 부분 컬러에 _emailborderColor을 넣었습니다.

decoration: ShapeDecoration(
  shape: RoundedRectangleBorder(
      side: BorderSide(
        width: 1,
        color: _emailborderColor,
      ),
      borderRadius: BorderRadius.circular(8)),
),

 

그런후 메서드 하나를 만들어줍니다.

이친구는 인풋필드를 눌렀을때 컬러색을 바꿔주는 역활을 합니다.

void _onFocusChange() {
  setState(() {
    _emailborderColor =
    _emailfocusNode.hasFocus ? Color(0xFF4B0FFF) : Color(0xFFD1D1D1);
  });
}

 

 


상태관리

 

 

자이제 이친구들이 하나만 있는게 아니자나요?

비밀번호 눌렀을때 비밀번호 인풋필드색만 변해야되고 이메일을 눌렀을때 이메일 인풋필드 색이 변해야 되니까

 

initState() - 위젯이 처음 생성될 때 호출되는 메서드 ,

dispose() - 위젯이 더 이상 필요하지 않을 때 호출되는 메서드

 

상태관리를 해주는 매서드들 두가지를 알아 둬야됩니다.

쉽게 설명하면 initState() 이걸쓰는이유는

입력 필드에 포커스가 생겼을 때 반응하려면, 이곳에서 리스너를 추가해야 합니다.

그리고 필요없어졌을때 dispose() 를 불러서 다시 기본값으로 만들어야되니까 필요한겁니다.

@override
void initState() {
  super.initState();
  _emailfocusNode.addListener(_onFocusChange);
}

 

@override
void dispose() {
  _emailfocusNode.removeListener(_onFocusChange);
  _emailfocusNode.dispose();
  super.dispose();
}

 

리스너 뒤에 메서드를 넣는 이유는 그럼 뭘까요

우리가만든 색바꾸는 메서드를 넣어야 작동하니까 넣죠??

 

그럼 준비는 끝났습니다.

 

 

 

아까 만든 UI에 넣은것들을 총 정리하면 

Container(
              width: 428,
              height: 299,
              padding: EdgeInsets.symmetric(horizontal: 24),
              child: Column(
                children: [
                  Container(
                    width: 146,
                    height: 29,
                    decoration: BoxDecoration(
                        image: DecorationImage(
                            image: AssetImage('assets/image/logo_10.png'))),
                  ),
                  SizedBox(height: 48),
                  Column(
                    children: [
                      Container(
                        height: 48,
                        width: 428,
                        padding:
                        EdgeInsets.symmetric(vertical: 12, horizontal: 12),
                        decoration: ShapeDecoration(
                          shape: RoundedRectangleBorder(
                              side: BorderSide(
                                width: 1,
                                color: _emailborderColor,
                              ),
                              borderRadius: BorderRadius.circular(8)),
                        ),
                        child: TextFormField(
                          controller: _textController,
                          focusNode: _emailfocusNode,
                          onChanged: (text) {
                            setState(() {});
                          },
                          style: TextStyle(
                            color: Color(0xFF3D3D3D),
                            fontSize: 16,
                            fontFamily: 'Pretendard',
                            fontWeight: FontWeight.w500,
                            height: 1.0,
                            letterSpacing: -0.4,
                          ),
                          textInputAction: TextInputAction.next,
                          decoration: InputDecoration(
                              border: InputBorder.none,
                              focusedBorder: InputBorder.none,
                              contentPadding: EdgeInsets.only(bottom: 10),
                              hintText: '이메일입니다.',
                              hintStyle: TextStyle(
                                color: Color(0xFF888888),
                                fontSize: 16,
                                fontFamily: 'Pretendard',
                                fontWeight: FontWeight.w500,
                                height: 1.0,
                                letterSpacing: -0.4,
                              ),
                              suffixIcon: _textController.text.isNotEmpty
                                  ? IconButton(
                                  onPressed: () {
                                    _textController.clear();
                                    setState(() {});
                                  },
                                  padding:
                                  EdgeInsets.only(bottom: 10, left: 60),
                                  icon: Icon(Icons.cancel,
                                      color: Color(0xFF888888)))
                                  : null),
                        ),
                      ),

 

 

final _textController = TextEditingController();
final FocusNode _emailfocusNode = FocusNode();
Color _emailborderColor = Color(0xFFD1D1D1); // 기본 테두리 색상


@override
void initState() {
  super.initState();
  _emailfocusNode.addListener(_onFocusChange);
}

@override
void dispose() {
  _emailfocusNode.removeListener(_onFocusChange);
  _emailfocusNode.dispose();
  super.dispose();
}

void _onFocusChange() {
  setState(() {
    _emailborderColor =
    _emailfocusNode.hasFocus ? Color(0xFF4B0FFF) : Color(0xFFD1D1D1);
  });
}

 

 

쉽죠?

 

728x90