Flutter TextField(String, int, datePicker) Feat.Future

강정우·2023년 5월 18일
0

Flutter&Dart

목록 보기
27/87
post-thumbnail

TextField

  • 위 위젯은 input 태그와 동일하다.

  • 최대, 최소 값을 입력할 수 있어서 굉장히 편리하고 또 input type을 지정할 수 있어서 굉장히 편리하다.

  • 그렇다면 TextField로 입력받은 값을 어떻게 하여 저장할 수 있을까? => 방법은 2가지이다.

1. 프레임웤 메모리에 저장하기

  • 위 코드는 stateful한 위젯에서 state Class를 추출하였다.

  • var 변수를 선언하여 클릭하면 저장할 변수를 메모리에 할당하였다.

  • _saveTitleInput이라는 함수를 선언하여 input값을 받고 해당 값을 위에서 선언한 변수에 담도록 함수를 선언하였다.

  • 마지막으로 TextField 객체 내에서 속성으로 선언하여 onChanged 즉 내부의 값이 바뀔때마다 변수를 갱신하도록 작성하였다.

  • 이때 값이 변한다고 해서 딱히 setState를 해줄필요는 없다 왜냐하면 해당 변수로 딱히 UI를 업데이트할꺼가 아니기 때문이다.

  • 마지막으로 위 사진은 used to be를 적고 save Expense를 눌렀을 때 print되도록 한 코드가 잘 작동되는 모습이다.

2. TextEditingController

  • 이는 객체로서 TextField에 값이 들어가고 나가는 것을 모두 관리, 관장해주는 객체이다.

  • 하지만 이 객체를 쓸 때 굉장히 매우 중요한 부분이 있는데 바로 사용후 메모리를 닫아줘야한다. 마치 JAVA에서 Scanner를 사용한 후 다시 닫아주는 것 처럼 말이다!

dispose

  • 사실 이 dispose라는 함수는 ininState, build 메서드와함께 Stateful 위젯을 구성하는 3대 라이프 사이클이다.

  • 이는 Widget이 제거될 때 즉, unmounted될 때 flutter에 의해 자동적으로 실행되는 메서드이다.

  • 이 dispose 메서드는 State class를 상속받는 class에서만 사용가능하다. 즉, 이말은 Stateful한 class에서 만 사용가능하다.

  • 예제 코드는 위와 같다. TextEditingController 라는 객체를 생성 후 final 변수에 담고 이를 쓰지 않을 때를 대비해 dispose 함수를 선언해준다.
    이때 dispose만 쳐도 IDE가 추천해주는 메서드가 뜨니 그것을 구현해서 사용하면 된다.

  • 그리고 만약 당신이 여러개의 field값을 입력 받아야한다면 당연 여러개의 controller가 필요하다.

  • 이번엔 TextEitting Contoller를 이용하여 똑같이 구현한 모습이다. 즉, controller 속성값을 쓰든, onPressed나 onChanged를 이용하여 작성해도 된다.

  • 또한 여기서 controller를 열어두면 메모리를 계속 사용하니까 다 사용했다면 반드시 dispose로 닫아줘야한다.
    이렇게 귀찮은 대신 사용자의 input 값을 flutter가 관리해줌으로써 추후 언제든 extract할 수 있다.

  • 그리고 여느 언어와 마찬가지로 아무리 int 타입을 받아도 결국에 저장되는 값으로 String으로 저장된다.

TextFormField

  • decoration, keyboardType, autocorrect, textCapitalization 등 우리가 입력할 때 굉장히 불필요하게 수정이나 대문자를 강권했던 부분들을 모두 바꿀 수 있다.

숫자를 받기

  • 바로 위에서 언급한 대로 필드별 controller를 생성해줬다.

  • 숫자를 받기 위해선 keyboarType을 TextInputType 객체에서 number로 지정해줬다.

  • 또한 가격을 받기위해 접두어 prefix를 붙여주었다.

  • 추가적으로 제일 밑에 보면 Navigator.pop(context) 라는 코드를 볼 수 있는데 우선 Navigator 객체는 추후 다루도록 하겠다.
    우선 .pop() 함수는 스택 구조에서 제일 위에 위치한 navigation을 pop 즉, 마지막 노드를 제거하는 것이라 볼 수 있다.

  • 그리고 내부에 들어있는 context객체는 build메서드에 있는 BuildContext 타입의 context객체이다. 즉, 현제 context(widget)을 날려버리겠다 라는 뜻이다.

  • 위 사진은 keyboartType과 prefix가 잘 동작하는 모습이다.

DatePicker

Expaned 필수

  • 이때 Row나 Column안에 Row나 Column이 있으면 어떻게 해라? => Expanded로 제한을 둬라~

  • 이건 TextField도 마찬가지이다. 텍스트 필드는 이런 Row나 Column위젯에 배치될 때 문제가 생기는 위젯이 될 수 있기 때문이다.
    그이유는 가로로 최대한 많은 공간을 차지하려고 하기 때문이다.

  • Row 위젯은 기본적으로 차지할 수 있는 공간의 양을 제한하지 않기 때문에 플러터가 이 조합을 스크린에서 렌더링할 때 문제가 발생한다.
    그래서 TextField도 Expand 위젯으로 랩해야 한다.

  • 화면에 나오는 만큼 공간을 차지하지만 그 이상은 안 되기 때문이다.

showDatePicker()

  • 아래 사진은 showModal() 메서드로 모달을 띄워주는 함수이다. 이와 굉장히 비슷하게 생긴 showDatePicker함수이다.

  • 둘다 show라는 prefix가 붙고 또 context라는 props가 존재한다.

  • 그리고 아래 사진은 이상없이 작동하는 사진이다.
    이때 위 코드에서 initialDate는 showDatePicker가 실행되었을 때 표시되는 날짜이고 firstDate는 선택 가능한 시작을 lastDate는 선택 가능한 마지막 날이다.

Future

  • 다른 뜻이 아니고 말 그대로 "미래" 이다. 근데 미래 뭐? => 미래에 선언될 변수라는 뜻이다.

  • 플러터는 내부적으로 기억해두었다가 미래에 어떤 값이 선택되면
    실행될 함수를 등록할 수 있게 해 주는 것이다. 무슨 말이냐면

  • 일단 그 값(날짜 선택기가 반환하는 future 객체)이 사용 가능해지면 함수는 해당 객체에 "메서드"를 호출해 등록할 수 있다.

  • 그래서 이 미래 객체는 중요한 부분인데 만약 사용자가 선택한다면 그즉시 반환된다.
    그럼 이제 뭔가 감이 오지 않나? 맞다 마치 Promise처럼 .then()을 사용할 수 있다.

  • .then() 이 있으면 뭐다? async, await도 존재한다~ 그런데 얘는 추후 http req에서 더 자세히 다뤄보자

  • 무튼 위 DatePicker가 선택되면 그때 UI를 업뎃 해줄꺼니 setState 메서드에 넣고 돌리면 된다.
    다만 이 Future 객체를 다룰 땐 optional에 조금 더 신경을 써줘야한다. 우선 변수 선언부터 봐보자.

Future 객체의 변수선언

  • 당연 객체 타입에 맞추서 선언하고 이때 Type 부분에 optional 키워드를 사용해줘야한다. 왜냐? 초기화 당시엔 null일 수 있으니 말이다.

  • 또한 해당 객체를 사용할 땐 잘 활용을 해야한다. 현재 위에서 formatter로 사용하고있는 포맷터 객체는 모델에 미리 선언해둔 객체를 가져다가(import) 다시 쓰는 것이다. 그리고 이땐 당연 해당값이 무조껀 있어야하는데 이미 3상연산자로 반드시 값이 있을 때만 들어오기 때문에 !로 또 처리해주면 끝@!
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글