2023-10-22.12.45.57.mov
해결과정
UISegmentControl 클래스를 상속받는 커스텀 UnderlineSegmentControl 정의
didMoveToSuperView 라이프사이클에서 기본적인 언더라인 세그먼트 구현을 위한 기본설정 (setBackgroundImage & 서브뷰 추가)
언더라인 뷰의 초기 너비값은 segmentControl 너비값을 전체 아이템 갯수로 나눈 값
1. 세그먼트 탭 이후
titleTextAttributes 함수를 통해 텍스트의 intrinsicSize 너비값을 구한다
세그먼트 컨트롤 너비는 상위 뷰의 오토레이아웃 설정 과정에서 고정되므로 아이템 갯수만큼 나눈 이후의 너비값도 고정된다
공평하게 나뉜 너비값에서 아이템별 텍스트 고유 사이즈를 빼주고 이를 2로 나누면 언더라인 뷰의 origin x값의 위치가 결정된다
UIView animate 클로저에서 위치를 지정
func moveUnderlineView( ) {
let fontAttributes = titleTextAttributes ( for: . normal)
guard let title = titleForSegment ( at: self . selectedSegmentIndex) else { return }
let size = title. size ( withAttributes: fontAttributes)
let perSegmentWidth = self . bounds. width / CGFloat( self . numberOfSegments) // 세그먼트 별 길이
let underlineFinalXPosition = ( perSegmentWidth * CGFloat( self . selectedSegmentIndex) ) + ( perSegmentWidth - size. width) / 2
self . underlineView. frame. origin. x = previousXPosition
UIView . animate (
withDuration: 0.1 ,
animations: {
self . previousXPosition = underlineFinalXPosition
self . underlineView. frame. origin. x = underlineFinalXPosition
}
)
}
세그먼트 탭은 상위 뷰에서 rx 컨트롤 이벤트를 통해 drive하여 함수 호출
2. 언더라인 너비 업데이트
초기 언더라인 너비값은 고정이지만 텍스트 고유 사이즈에 따라 너비를 업데이트 해줘야 함
예컨대 포즈피드는 네글자, 포즈톡&북마크&포즈픽은 세 글자이므로 고유 사이즈가 다름
심지어 자음별 크기에 따라 너비값이 다르게 산정되는 경우도 있을 수 있다
moveUnderlineView 함수에서 사용한 것과 동일하게 텍스트 고유 사이즈를 얻고 UIView.animate 클로저에서 너비를 업데이트해준다
언더라인뷰는 UnderlineSegmentControl 클래스의 서브 뷰이므로, self.layoutIfNeeded()를 클로저에서 호출해주면 레이아웃이 자동으로 업데이트된다.