[ios] 커스텀 탭바(TabBar) 만들기
안녕하세요. 오늘은 기본 TabBar가 아닌 커스텀 TabBar를 만들어보려 합니다. 안드로이드에서와는 다르게 iOS에는 TabBar는 하단에 고정되어있고 이는 변경할 수 없습니다. 그렇기 때문에 하단이 아닌 NavigationBar 밑이나 다른 곳에 위치시키기 위해서는 TabBar를 흉내 내는 뷰를 만들어주어야 합니다.
저는 이를 위해서 UICollectionView
를 사용하였습니다. 또한 저는 공부 목적으로 만들어본 것이기 때문에 제가 사용한 방법이 정답이라고는 할 수 없으나 엇비슷하게 흉내는 내볼 수 있었습니다. 그럼 제가 만들어본 커스텀 TabBar를 소개해드리도록 하겠습니다.
Implementation
저는 먼저 다음과 같은 뷰의 구성으로 TabBar를 만들어주기로 했습니다.
보다 보기 쉽게 하기 위해 뷰들 간의 간격을 띄어놓았습니다. 실제로 만들어질 TabBar의 색과도 차이가 존재합니다.
먼저 노란색 뷰는 UICollectionViewCell
로 UITabBarItem
역할을 합니다. 그리고 핑크색 뷰는 현재 어떤 UITabBarItem
을 선택했는지를 알려주는 일종의 indicator 뷰의 역할을합니다. 그리고 이렇게 UICollectionView
와 indicator 뷰를 담는 파란색 컨테이너 뷰를 만들어줄 것입니다.
그럼 하나 하나 만들어보도록 하겠습니다.
먼저 필요한 뷰들의 기본적인 생성은 다음과 같습니다. UICollectionView
에 필요한 UICollectionViewCell
과 몇 가지 설정을 해주도록 하겠습니다. 저는 CustomCell
이라는 이름의 UICollectionViewCell
을 상속받는 클래스를 만들어주었습니다.
UICollectionViewCell
Register Cell & UICollectionView Setup
이제 만든 CustomCell
을 UICollectionView
에 등록을 하고 몇몇 설정을 마무리하도록 하겠습니다.
indicator 뷰도 만들어줄 것이기 때문에 showHorizontalScrollIndicator
를 false
로 설정해주었습니다. 그리고 .reusableIdentifier
는 존재하지 않는 프로퍼티인데요! 이건 제가 Extension
을 통해 만들어준 프로퍼티로 클래스 자신의 이름을 reusableIdentifier
로 사용합니다. 코드는 다음과 같습니다.
Views Layout Setup
이제 UICollectioView
의 설정까지 끝났고 이젠 생성한 뷰들을 조립해보도록 하겠습니다.
- indicator 뷰를 현재 어떤 탭을 선택했냐에 따라 움직여주기 위해
leadingAnchor
의 constant
를 조정해줄 것이기 때문에 이렇게 따로 프로퍼티로 뺐습니다.
- TabBar를
NavigationBar
밑에 위치시킬 것이기 때문에 self.view.topAnchor
를 사용하면 안됩니다. 이는 NavigationBar
를 무시하고 뷰의 맨위로 붙어버리기 때문에 NavigationBar
뒤로 가려지게 됩니다. 그렇기 때문에 self.view.safeAreaLayoutGuide.topAnchor
를 사용합니다.
- 4개의
CustomCell
로 4개의 아이템만을 보여줄 것이고 4개의 같은 너비 셀로 UICollectionView
을 채울 것입니다. 그리고 현재 어떤 탭이 선택되었는지를 알려주는 indicator 뷰도 셀의 너비와 같은 값을 할당해주었습니다.
UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
그럼 이제 UICollectionView
의 프로토콜들의 메소드를 구현해보도록 하겠습니다.
-cellForItemAt, numberOfItemsInSection
필수로 구현해야하는 두 메소드를 구현해보았습니다.
-sizeForItemAt
UICollectionViewCell
의 실질적인 크기를 지정해주는 메소드도 구현해보겠습니다.
height
값은 customTabBarCollectionView
의 heightAnchor
의 constant
값과 같습니다.
-insetForSectionAt, minimumLineSpacingForSectionAt
이젠 CustomCell
들의 간격을 조정하는 메소드를 구현해보도록 하겠습니다.
CustomCell
들은 UICollectionView
내에서 상하좌우 모두 꽉 차있어야 하므로 위와 같은 인셋을 주었습니다.
- 각각의
CustomCell
역시 서로 간격 없이 UICollectionView
를 채워야하기 때문에 위와 같은 값을 지정해주었습니다.
여기까지가 뷰의 기본 셋업이였습니다. 이제는 탭을 선택하였을 때 indicator 뷰의 움직임과 선택한 탭을 다른 탭과 구분해주기 위한 작업을 해보도록 하겠습니다.
-didSelectItemAt didDeselectItemAt
didSelectItemAt
을 통해 선택한 CustomCell
의 label
의 색을 바꿔줄 것이고 선택한 탭의 아래로 indicator 뷰를 움직여줄 것이기 때문에 선택한 CustomCell
에 따라 너비만큼 indicator 뷰의 leadingAnchor
의 constant
값을 바꿔주고 이를 애니매이션으로 그려주었습니다.
didDeselectItemAt
을 이용한다면 1번 탭(CustomCell
)을 선택하고 2번 탭을 선택하면 자동으로 1번 탭은 deselect
됩니다. 그렇기 때문에 이를 활용하여 새로운 탭을 클릭했을 때 이전에 선택한 탭의 textColor
를 원래의 상태로 바꿔주는 것을 구현했습니다.
그리고 마지막으로 처음 모든 뷰가 로드되었을 때 첫번째 탭을 선택된 탭이라고 지정하기 위해 cellForItemAt
메소드를 살짝 수정해주었습니다.
이렇게되면 첫 번째 탭은 뷰가 로드되었을 때 선택된 셀이라 시스템이 인지하고 textColor
를 변경합니다. 그리고 다른 탭을 눌렀을 때는 역시 didDeselectItemAt
메소드에 의해 원래의 textColor
로 바뀌게 됩니다.
마무리
이렇게 만들어진 커스텀 TabBar의 모습은 다음과 같습니다.
막 공부를 시작했을 때는 이를 어떻게 구현해야할지 막막하였으나 그래도 꾸준히 공부를 하니 이젠 어렵지 않게 직접 원하는 뷰와 액션을 만들수 있게 된 것 같습니다. 아직은 부족한 점이 많기 때문에 더욱 열심히 공부를 해야겠습니다. 혹시 제가 사용한 방법이 옳지 않거나 보다 좋은 방법이 있다면 피드백 부탁드리겠습니다. 감사합니다.
Source : github