이번시간에는 UIKit에서 세그멘트 컨트롤을 커스텀해서 쓰느법을 알아보려고 합니다.
다른글들을 많이 찾아봤는데 다들 스냅킷만 쓰더라구요?
이번 프로젝트는 스냅킷을 쓸만큼 뭐가 많지않아서 그냥 만들기로해서
하루죙일 스냅킷 안쓰고 그걸 똑같이 그대로 UIKit 네이티브 코드로 옮겨서 했는데 안되더라구요...
그래서 해외글도 찾아보니까 그냥 x좌표를 옮겨버리더라구요?(진즉에 찾아볼껄;;)
그래서 나온 코드입니다.. 와 진짜 너무 힘들었어요ㅠㅠ
우선 결과물은 아래와 같습니다.
그럼 코드로 보시죠~
예시코드
private let segmentControl: UISegmentedControl = {
let segment = UISegmentedControl()
segment.insertSegment(withTitle: "Month", at: 0, animated: true)
segment.insertSegment(withTitle: "Day", at: 1, animated: true)
segment.selectedSegmentIndex = 0
segment.setTitleTextAttributes([
NSAttributedString.Key.foregroundColor: UIColor.gray,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16)], for: .normal)
segment.setTitleTextAttributes([
NSAttributedString.Key.foregroundColor: UIColor.black,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16)], for: .selected)
segment.selectedSegmentTintColor = .clear
segment.setBackgroundImage(UIImage(), for: .normal, barMetrics: .default)
segment.setDividerImage(UIImage(), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
segment.addTarget(self, action: #selector(changeUnderLinePosition), for: .valueChanged)
segment.translatesAutoresizingMaskIntoConstraints = false
return segment
}()
private let underLineView: UIView = {
let view = UIView()
view.backgroundColor = .black
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
우선은 위와 같이
두개의 세그먼트를 갖는 세그먼트 컨트롤과 밑줄을 위한 뷰를 만들어줍니다.
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(segmentControl)
self.view.addSubview(underLineView)
let safeArea = self.view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
segmentControl.topAnchor.constraint(equalTo: safeArea.topAnchor),
segmentControl.centerXAnchor.constraint(equalTo: safeArea.centerXAnchor),
segmentControl.widthAnchor.constraint(equalTo: safeArea.widthAnchor, multiplier: 0.4),
segmentControl.heightAnchor.constraint(equalToConstant: 20),
underLineView.topAnchor.constraint(equalTo: segmentControl.bottomAnchor, constant: 10),
underLineView.leadingAnchor.constraint(equalTo: segmentControl.leadingAnchor),
underLineView.widthAnchor.constraint(equalTo: segmentControl.widthAnchor, multiplier: 0.5),
underLineView.heightAnchor.constraint(equalToConstant: 2)
])
}
그다음 뷰를 현재 뷰컨에 추가해주고
segmentControl과 underLineView를 각각 제약조건을 추가해줍시다.
너무 간단해서 딱히 설명할게 없죠?
@objc
private func changeUnderLinePosition(_ segment: UISegmentedControl) {
let halfWidth = segmentControl.frame.width / 2
let xPosition = segmentControl.frame.origin.x + (halfWidth * CGFloat(segmentControl.selectedSegmentIndex))
UIView.animate(withDuration: 0.2) {
self.underLineView.frame.origin.x = xPosition
}
}
마지막으로 underLine을 움직이기 위한 메서드를 만들어줍니다.
지금은 세그먼트가 두개니까 halfWidth라고 반쪽넓이를 구했는데 동적으로 조절한다면 뒤에 나누는 숫자를
segmentControl.numberOfSegments를 쓰면 좋을거같습니다.
다음으로 xPosition 변수를 만들어줍니다.
underLine이 맨처음에 segmentControl과 leading이 일치했죠?
그래서 xPosition은 segmentControl의 x좌표에 인덱스(0,1)에 맞춰서
0일땐 초기 위치, 1일땐 너비의 절반만큼 더해서 옮깁니다.
그리고 animate()를 통해서 0.2초동안 애니메이션과 함께 x좌표를 바꿔서 부드럽게 움직이는것처럼 만들어줍니다.
아래 두개의 글을 참고했습니다.
https://mini-min-dev.tistory.com/226
https://nitishrajput912.medium.com/underline-segment-control-programmatically-swift-d2924842621a
'공부 > Apple' 카테고리의 다른 글
[Swift] uitableview 선택 유지 해제(deselectRow) (1) | 2024.07.24 |
---|---|
[UIKit] 이미지를 이미지뷰에 맞추기(clipToBounds) (0) | 2024.06.24 |
[Swift] DateFormat 정리 (0) | 2024.06.21 |
[SwiftUI] .fileImporter()로 파일 불러오기 (0) | 2024.06.17 |
[SwiftUI] NSSavePanel로 파일 저장하기 (0) | 2024.06.06 |