초기 세팅
SVG 라이브러리
SVG 이미지를 사용하기 위한 SvgPicture 위젯은 외부 라이브러리이므로 라이브러리 연결이 필요하다. SVG 라이브러리를 pubspec.yaml 파일에서 연결해준다. 사용할 svg 이미지는 assets 디렉토리를 생성 후 옮겨둔다.


MainPage
화면 이동을 위한 라우팅
routes 속성은 Map 타입으로 String과 Function 타입을 받는다.
initialRoute 속성으로 앱의 첫 페이지를 설정한다.


페이지 분리

LoginPage
SVG
SVG는 벡터 이미지로 화면의 크기가 변해도 사진이 깨지지 않는다는 장점이 있다.

SVG 이미지 넣기

ListView로 감싸기
전체 화면을 스크롤이 되는 ListView로 감싼다. Column으로 감싸지 않는 이유는 나중에 만들게 될 TextFormField 영역을 터치하면 입력을 위해 키보드가 올라오면서 화면에 그림을 그릴 수 없는 영역이 생기게 된다. 이를 inset 영역이라고 한다. inset 영역에 의해 그림을 그릴 수 없을때 스크롤이 없으면 overflow 오류가 발생한다.

텍스트 추가 후 Column으로 감싸기
예시 완성 화면을 보면 로고 이미지와 Login이라는 텍스트가 나란히 위치하는데 이는 Column으로 감싸면 한 묶음으로 처리 가능하다.

Column → MLogo 위젯으로 추출하기
로고는 홈화면에서도 사용되므로 모듈화하여 위젯으로 추출한다.
모듈화하게 되면 name이라는 변수를 받게 된다. 이때 변수는 null 값이 들어가도 null이라는 문자열 자체가 들어가서 안 터지게끔 처리하여 안전한 “$변수” 형태로 넣는 것이 좋다.


사용자 입력 받기
html에서 사용자 입력을 받았던 인풋태그 대신 플러터에서는 TextFormField를 사용한다. TextFormField는 decoration 속성으로 꾸미는데 InputDecoration 객체를 이용하여 hintText, border 등 속성을 통해 입력 필드를 커스터마이징할 수 있다.


입력 필드 border 설정
입력 필드의 border 설정은 입력필드를 터치하기 전인 기본 border 디자인(enabledBorder)과 입력 필드를 터치하여 포커스된 포커스 디자인(focusedBorder), 그리고 프론트엔드 유효성 검사를 통해 에러 발생 시 기본 디자인인 기본 에러 디자인(errorBorder), 에러 발생 시 포커스된 에러 포커스 디자인(focusedErrorBorder) 총 4가지가 한 세트라고 생각하면 된다.


TextFormField → MTextField 위젯으로 추출하기
위젯으로 추출하고 난 뒤 component로 파일도 분리한다.

MTextField 위젯 모듈화하기
MTextField 위젯은 username을 받는 입력 필드뿐만 아니라 비밀번호를 받는 입력 필드로도 재사용 가능하도록 모듈화한다.


비밀번호 가리기
입력받는 필드가 비밀번호일 경우 노출되지 않도록 **** 처리해주는 것이 좋다. 이때 bool 타입의 isPassword라는 필드를 만든 뒤 선택적 매개변수로 처리하여 false로 초기화되도록 설정한다. password일때는 isPassword : true를 인수로 함께 전달하고 password가 아닐때는 생략한다. **** 처리는 TextFormField의 obscureText 속성을 통해 가능한데 obscureText가 true이면 글자가 가려지고 false이면 원래대로 글자가 보이도록 설정할 수 있다.


버튼 만들기
ElevatedButton 위젯으로 버튼을 만들고 style 속성을 사용하여 커스터마이징한다.
- TextStyle → 텍스트 색깔 지정
- ElevatedButton.styleFrom() → 버튼 크기 및 색깔 지정
- backgroundColor → 버튼 색깔
- fixedSize → 버튼 크기

ElevatedButton → MButton 위젯으로 추출 및 모듈화



여백주기
여백을 줄 때 전체 화면은 ListView 위젯이 차지하고 있고 ListView는 스크롤이 있기 때문에 높이의 제한이 없다. 따라서 이 경우 화면의 남은 공간만큼 확장하는 Expanded나 Spacer 위젯을 사용할 수 없다. 그러므로 SizedBox를 이용하여 여백을 주는 것이 좋다. 이때 Size.dart 파일을 만들어서 값을 정해두고 사용하면 무분별한 사이즈 지정을 막고 통일감을 줄 수 있다.


MTextField + MButton → MForm 위젯으로 추출하기
MTextField 두 개와 MButton은 Column 기준으로 나란하게 배치되어있으므로 Column으로 감싼 뒤에 위젯으로 추출한다.

MForm 위젯 - Column 때문에 생긴 일
위젯으로 추출하기 위해 Column으로 감싼 다음 버튼이 갑자기 줄어든 것을 볼 수 있다. MButton을 보면 fixedSize 속성을 통해 width가 double.infinity로 설정되어 있는 것을 알 수 있는데 이 설정이 제대로 적용되지 않는 상태이다. 즉, 버튼의 부모인 Column에 제약 때문에 발생한 상황이다. 버튼의 부모인 Column은 가로 제약을 주지 않는다. 이로 인해 자식인 Button은 불확실성 때문에 최소한의 너비만 잡으려고 한다. 그렇기 때문에 fixedSize로 설정한 값이 아닌 자식인 Text의 너비만큼 잡게 된다.

Column 제약조건 해결하기 (1) - ListView + shrinkWrap 설정
Column 대신 ListView로 버튼 크기를 원하는대로 다시 설정 가능하지만 리스트를 만들고자 하는 게 아니므로 사용하지 않는다.

Column 제약조건 해결하기 (2) - Container + width 설정

Column 제약조건 해결하기 (3) - SizedBox + width 설정

Column 제약조건 해결하기 (4) - Row + Expanded
버튼만 Column의 자식들 중 Button만 Row로 처리해서 Expanded를 걸어준다.

Column 제약조건 해결하기 (5) - Column 유지 + crossAxisAlignment 설정
MTextField와 MButton을 감싸는 Column은 유지하되 crossAxisAlignment를 stretch로 설정하여 Column의 반대축인 가로를 끝까지 늘어날 수 있도록 한다.

전체 양옆으로 여백주기
Padding으로 감싸서 여백을 준다.

나머지 여백 + 폰트 설정
입력 필드 사이와 입력 필드와 버튼의 사이에 여백을 준다.

로고의 Login 폰트에도 size와 weight를 설정해준다.

폼에 입력된 문자 가져오기
TextEditingController는 입력 필드의 텍스트 상태를 관리하는 클래스로 입력 필드 상태를 추적하는 객체 생성하여 TextFormField에 연결하면 사용자가 입력한 텍스트를 읽어올 수 있다.
따라서 MTextField에 controller를 연결하고 무조건 받아올 것이기 때문에 MTextField의 두 번째 시그니처로 지정해준다.

객체(_username, _password)를 만들어서 controller에 전달하면(MTextField는 두 번째 시그니처로 controller를 받는다.) _username.text, _password.text로 입력받은 값을 찾을 수 있다. html의 id를 걸어주는것과 비슷하다고 볼 수 있다.

글자를 땡겨오는 것ㄱ = 버튼 클릭시 발동해야된다
근데 행위가 버튼 안에 잇음
입력 필드에 입력한 문자를 땡겨오는 일은 버튼 클릭 시 발동되어야 한다. 이때 행위가 버튼 안에 있으므로 전달해줘야 한다


유효성 검사
TextFormField의 validator 속성을 통해 유효성 검사가 가능하다.
submitㅎ하는순간 validator가 발동하도록
true가 되면 화면 넘어갈 수있게
null을 리턴하면 문제없고 문자열을 리턴하면 input 태그 밑에 찍힘
Share article