상세 컨텐츠

본문 제목

Animation 활용해 TabBar 구현하기

iOS

by 쑤야. 2023. 4. 27. 20:54

본문

나는 라이브러리를 최대한 사용하지 않으려고 하는 편이다..

아래 첨부한 기능인 Tab Item 전환 기능을 TabMan 라이브러리를 활용하지 않고 구현해보고자 한다.

 

 

이번 포스팅에서 다룰 내용은 탭 상단(아이템) 부분 Animation 적용에 대해서만 다룰 예정이다. 각 Tab에 대한 스크롤/페이징 되는 UI는 현재 프로젝트에서 중요성이 떨어지는 부분으로 나중에 시간이 남으면 추가해 보도록 하겠다.

 

CollectionView 데이터 바인딩은 이미 되어 있다는 가정하에 설명을 진행하도록 하겠다.


1. TabBar Item 선택 감지

changeSelectCell 메서드 내부에서 UI 변경 작업을 진행했다.

아래 작성한 코드에서는 생략했지만 changeSelectCell 메서드 이외에도 처리한 작업들이 있기 때문이다.

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    changeSelectCell(faqId: indexPath.row)
    ...
}

2. Cell 선택 여부 변경

ServiceTitleCollectionViewCell에 isSelect 프로퍼티를 통해 UI가 변경되도록 구현해놓은 상태이다.

이전에 선택됐었던 Cell은 willSet 감시자를 통해 선택 취소가 되며, 새로 선택된 Cell은 didSet 감시자를 통해 선택 버전의 UI가 적용된다.

private func changeSelectCell(faqId: Int){
    selectServiceCell = mainView.serviceCollectionView.cellForItem(at: [0,faqId], cellType: ServiceTitleCollectionViewCell.self)
    changeSelectCellUnderLineLayout()
}
private var selectServiceCell: ServiceTitleCollectionViewCell!{
    willSet{
        selectServiceCell?.isSelect = false
    }
    didSet{
        selectServiceCell.isSelect = true
    }
}

/*

ServiceTitleCollectionViewCell의 isSelect 프로퍼티

var isSelect: Bool = false{
    didSet{
        titleLabel.textColor = isSelect ? UIColor.zatchPurple : .black20
    }
}
*/

3. Animation을 활용한 UnderLine 레이아웃 변경

이 부분이 이번 포스팅의 목적이다.

 

원래는 Snapkit 라이브러리를 사용하기 때문에 Snapkit 메서드를 최대한 활용하고자 updateConstraints나 remakeConstraints를 활용해 레이아웃을 조정하려고 했었다.

하지만 updateConstraints의 경우 기준이 되는 View를 변경하지 못하고 offset 등의 수치만 변경이 가능하기 때문에 구현하려는 기능에는 적합하지 않다고 판단을 했다.

remakeConstraints를 활용하게 될 경우, 변하지 않는 높이와 하단까지 매번 재설정을 해줘야 하기 때문에 이것도 부적합하다고 판단했다.

 

구글링을 통해 찾은 해법은 underLineConstraints의 activate, deactivate 메서드를 활용하는 방법이다.

 

activate 메서드 공식문서를 통해 확인해보면,

 

Parameters

: An array of constraints to activate.


배열에 activate 할 제약조건을 넣어주면 된다고 나와있다.

즉, 원하는 조건들만 activate, deactivate 하여 레이아웃을 조정할 수 있는 것이다.

 

구현한 코드를 살펴보겠다.

private var underLineConstraints: [NSLayoutConstraint]!

private func changeSelectCellUnderLineLayout(){
    
    defer {
        animateChangeUnderLineLayout()
    }
    
    if underLineConstraints != nil {
        NSLayoutConstraint.deactivate(underLineConstraints)
    }
    
    underLineConstraints = [
        selectCellUnderLine.leadingAnchor.constraint(equalTo: selectServiceCell.leadingAnchor),
        selectCellUnderLine.trailingAnchor.constraint(equalTo: selectServiceCell.trailingAnchor)
    ]
    
    NSLayoutConstraint.activate(underLineConstraints)
}

private func animateChangeUnderLineLayout(){
    UIView.animate(withDuration: 0.3) {
        self.view.layoutIfNeeded()
    }
}
  • 기존 레이아웃을 deactivate 하기 위해서 underLineConstraints 전역 변수 설정
  • 기존에 설정된 제약조건이 있는 경우만 (underLineConstraints이 nil이 아닌 경우) deactivate 실행
  • underLineConstraints에 새로 설정한 leading, trailing 레이아웃 제약 조건 담기
  • 새로운 레이아웃 activate
  • Animate 메서드를 통해 underLine의 레이아웃이 변경되는 과정을 애니메이션으로 제공

최종 구현한 모습이다

 

@ 참고

https://nsios.tistory.com/44

관련글 더보기