안녕하세요. Flutter 개발을 하고 있는 조현철입니다. 😀
오늘은 토스의 송금 화면을 구현해보려고 합니다. 토스앱의 메인화면은 당근마켓 홈화면과 구현 방식이 크게 다르지 않을 것 같아서 송금 화면을 선택했습니다.
이번에는 UI 뿐 아니라 데이터 관련 된 부분도 조금 소개를 드리려고 합니다. 제가 사용하는 방법이기 때문에 저는 이렇게 구현한다 정도로 생각해주시면 될 것 같습니다.
그럼 시작해 보겠습니다!
1. 영역구분
토스 송금화면은 크게 3개의 영역으로 나눌 수 있습니다. ①번 영역은 고정된 Tab 영역, ②번 영역은 Body 영역, ③번 영역은 bottomNavigation 영역입니다.
처음에 ①번 영역은 Scaffold의 appBar 로 추가를 할까 고민을 하다가 body에 배치하는 것으로 결정했습니다. 따라서 크게는 ①+② 영역은 body에 배치하는 구조입니다.
2. Body
2–1. Tab
Tab을 구현하려면 크게 TabBar와 TabBarView 를 구현해야 합니다. TabBar는 “추천”, “계좌”, “연락처” 버튼 영역이고, TabBarView는 Tab을 했을 때 보여질 페이지 입니다.
Tab이 선택이 되면 TabBarView가 해당 페이지로 이동해야 하는데 이 때 controller가 필요합니다. TabController를 직접 선언해서 사용해도 되지만 Tab의 경우 DefaultTabController위젯을 제공합니다. 해당 위젯 하위 위젯에서는 별도의 controller에 대한 설정없이도 TabBar와 TabBarView를 연결해 줍니다.
토스처럼 TabBar 디자인을 위해 TabBar의 바깥에 Container에 decoration을 설정했습니다. 그런데 Theme 위젯은 왜 주었을까요?
Theme위젯 없이 실행해 보면 아시겠지만 TabBar(“추천”, “계좌”, “연락처”)를 선택하면 Ripple(선택 애니메이션)효과가 나타나는데 이것을 없애기 위해서 Theme위젯을 통해 hightColor, splashColor를 보이지 않도록 했습니다.
TabBarView에 보면 3개의 위젯이 들어가는데 여기에 “추천”, “계좌”, “연락처” 페이지를 구현해주면 됩니다.
2–2. 추천
추천탭에는 비슷한 형태의 2가지 리스트가 존재하는 것을 볼 수 있습니다.
“내 계좌로”와 “최근 보낸 계좌로”를 보면 서로 약간 다릅니다. 계좌의 개수를 표한하는 부분, 메인으로 사용하는 계좌표시, 즐겨찾기 표시 같은 부분이 서로 다르지만 결국 형태는 비슷한 것을 알 수 있습니다. 2가지의 형태를 따로 구현을 할까 하다가 하나의 위젯에 파라미터를 이용하여 구분하는 방식으로 구현을 해 보았습니다.
우선은 영역을 먼저 잡아보도록 하겠습니다.
2가지 형태를 합쳐서 _accountItem() 하나로 만들었습니다. 이제 리펙터링을 진행하도록 하겠습니다.
먼저 2가지 형태를 구분하기 위해 enum을 선언하여 사용했습니다.
enum BlockType { MY_ACCOUNT, RECENT_ACCOUNT }
그 이후에 계좌와 관련된 정보를 넣어줄 AccountInfo class를 선언하고 또 AccountInfo를 list로 선언하여 2가지 형태에 대한 데이터를 넣을 준비를 하였습니다.
_accountList()에 blockType과 myAccountList, recentAccountList를 넘겨주고, _accountItem()에 blockType과 accountInfo를 넘겨서 상황에 맞게 분기 하도록 했습니다.
일부 설명을 이미지에 함께 작성해 놓았으니 이미지도 참고해주시면 될 듯 합니다. 맨 마지막에 전체 소스 경로를 작성해 두겠습니다.
2–3. 계좌
계좌 부분은 은행 선택과 계좌번호 입력으로 되어 있습니다. 계좌번호 입력의 경우 사용자가 키보드로 직접 입력하는 것이기 때문에 TextFormField로 구현 하면 됩니다. 하지만 은행 선택의 경우 사용자가 입력하는게 아니라 은행 리스트가 나오는 화면으로 이동하고 은행을 선택하면 오른쪽 사진과 같이 표현이 됩니다.
여기서는 은행을 선택하는 화면은 따로 구현하지 않고 “은행 선택” 영역을 누르면 카카오뱅크라고 입력되고 하단의 “확인”버튼을 활성화 되도록 구현하겠습니다.
소스에서 보면 계좌번호 입력 부분은 TextFormField 위젯으로 구현하였는데 은행 선택 부분은 위젯을 별도로 생성해서 구현했습니다. 위에서 이야기 했듯이 은행 선택을 누르면 다음화면이 나오고 거기서 은행 리스트 중에 하나를 선택하면 해당 은행 정보가 나오는 구조입니다.
bankName과 bankAccount를 flag처럼 사용하기 위해 텍스트가 비어있는지 채워져 있는지 확인 후 어떤 위젯을 보여줄지 선택하는 구조로 만들었습니다.
2–4. 연락처
여기는 크게 검색영역과 연락처리스트로 구성되어 있습니다. 검색영역은 스크롤되지 않고 연락처리스트만 스크롤 영역이라서 연락처 리스는 ListView로 구현하도록 하겠습니다.
Column으로 설정 후 검색영역 외의 영역은 Expanded로 설정하여 ListView가 검색영역을 제외한 나머지 전체 영역을 가져갈 수 있도록 했습니다.
검색영역에서 텍스트를 입력받아야 하기 때문에 TextFormField 위젯을 사용하였는데 밑줄이 보이는 것을 안보이게하기 위해서 border설정을 none으로 설정해줬습니다.
리스트에서 여백을 주기위해 ListView의 padding을 사용하였습니다. 이후에 개별 연락처 아이템간 여백을 주기 위해서 separatorBuilder에 height만 주었습니다.
3. BottomNavigationBar
bottomNavigationBar는 이전 포스팅에서 했던 것들과 크게 다르진 않지만 한가지 차이는 topLeft, topRight 부분이 borderRadius 처리 되어 있는 것과 회색으로 border 처리 되어 있는 것입니다.
bottomNavigationBar를 구현할 때 clipRRect를 사용했고 container의 color를 설정해 준 후에 padding을 줘서 0.5만큼 간격을 조정했습니다. 이 때 색상은 border 처럼 보이기위한 색상을 주었구요.
다시 container내부에 ClipRRect를 줘서 borderRadius 설정을 해주고 BottomNavigationBar를 사용했습니다. 그러면 실행결과와 같은 화면이 나오는 것을 볼 수 있습니다.
4. 전체 소스
위 내용에 해당하는 전체 소스도 함께 공유합니다. lib/src/toss 경로에 전체 소스가 있습니다. 확인하실 분들은 아래 링크를 확인해주시면 됩니다!
지금까지 토스의 송금화면을 구현해 보았습니다. 이번에는 TabBar와 TabBarView 사용하는것을 보여드리기 위해 송금화면을 구현해 보았는데 도움이 되셨는지 잘 모르겠습니다.😅 혹시 저와 다르게 구현하시는 분들의 의견도 듣고 싶습니다. 댓글로 알려주세요~
Next Flutter
다음은 채용사이트 중 하나인 원티드 앱의 홈화면을 다려보려고 합니다 혹시 다뤘으면 하는 UI가 있다면 알려주세요! 감사합니다! 🙏🏻🙏🏻🙏🏻