학습 개요
디자인 요구사항에 따라 Corner Radius 설정을 하나의 뷰에 별도로 처리해줘야 할 일이 생겼다.
왼쪽 위-아래는 2로, 오른쪽 위-아래는 8로 설정해야 한다.
let view = UIView()
view.layer.cornerRadius = 8
우리는 이런 식으로 UIView가 갖는 CALayer 타입 프로퍼티 layer에 cornerRadius로 설정해왔다.
위 코드의 경우 해당 뷰는 8의 곡선을 가질 것이다.
근데 각각 처리하려면 어떻게 할까 ?
학습 정리
CACornerMask
CALayer에 CACornerMask라는 옵션이 있다.
이걸로 4개의 꼭짓점을 가리키고, 개별적으로 설정해줄 수 있다.
만약 위처럼 내가 MaxX, MaxY에 대해서 설정을 했다면, 우측하단 해당 부분에만 Radius에만 적용이 된다.
“X가 가장 크고, Y가 가장 큰 위치에 대한 곡선”이라 생각하면 된다.
프레임 기준은 항상 좌측 상단을 기준으로 0, 0을 잡고 Y는 아래로 갈 수록 크기 때문이다.
class ViewController: UIViewController {
private let view2 = UIView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(view2)
view2.translatesAutoresizingMaskIntoConstraints = false
view2.backgroundColor = .systemBlue
NSLayoutConstraint.activate([
view2.widthAnchor.constraint(equalToConstant: 100),
view2.heightAnchor.constraint(equalToConstant: 100),
view2.centerXAnchor.constraint(equalTo: view.centerXAnchor),
view2.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
view2.layer.cornerRadius = 20
view2.layer.maskedCorners = [.layerMaxXMaxYCorner]
}
}
회전했을 때의 maskedCorners
그리고 회전해도 마찬가지이다.
이건 프레임 기반으로 동작해서 결국 현재 휴대폰의 회전률에 따라
좌측 상단으로부터 기준점을 잡고 Mask 위치를 잡는 것 같다.
정방향 | 좌로 90도 기울임 | 우로 90도 기울임
특정 영역은 2, 특정 영역은 8로 잡아야 하는 경우는?
위 예제는 전부 0 or 내가 설정한 값 이었는데, 디자인의 요구사항은 좌상단 좌하단은 2, 우상단 우하단 8로 설정해야 한다.
이 경우 UIBezierPath와 CAShapeLayer를 사용해야 한다.
UIBezierPath
직선 및 곡선 선분으로 구성된 경로로, 사용자 지정 보기에서 렌더링할 수 있습니다.
UIKit 프레임워크에 있는 클래스이다.
벡터 기반의 경로를 그릴 수 있는 클래스로, 이 경로를 통해 CAShapeLayer에 사용되거나 커스텀 UIView 모양을 잡을 수 있다.
직선, 곡선, 원, 사각형의 경로를 정의할 수 있다.
내부에 storke와 fill 메소드 등을 이용해 그림을 그릴 수 있고, CGPath를 통해 CAShapeLayer에도 적용할 수 있다.
let maskPath = UIBezierPath(
roundedRect: eventDetailView.bounds,
byRoundingCorners: [.topLeft, .bottomLeft],
cornerRadii: CGSize(width: 2, height: 2)
)
나는 위와 같이 maskPath를 설정했다.
eventDetailView.bounds의 왼쪽 위와 아래를 Size 2만큼 지정했다.
이를 나중에 CAShapeLayer에서 사용할 거다.
CAShapeLayer
벡터 그래픽을 사용해서 경로를 그릴 수 있는 클래스이다.
위에서 설명한 UIBezierPath와 CGPath를 사용하면, 이 레이어를 뷰 Layer에 적용하여 모양 커스텀이 가능하다.
그러니까 UIView.layer.mask에 내가 만든 CAShapeLayer를 적용시키면 개별 설정이 가능하다는 거임.
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath.cgPath
eventDetailView.layer.mask = maskLayer
위에서 내가 설정한 UIBezierPath 인스턴스 maskPath로 CAShapeLayer를 만들고,
maskLayer를 뷰에 적용해주면 해당 위치에 2만큼 적용이 가능하다.
최종 결과물
private func configureCornerRadius() {
// 1. 특정 모서리 (오른쪽 위, 아래)에 radius 8 적용
eventDetailView.layer.cornerRadius = 8
eventDetailView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]
eventDetailView.clipsToBounds = true
// 2. UIBezierPath를 사용하여 왼쪽 위, 아래에 radius 2 적용
let maskPath = UIBezierPath(
roundedRect: eventDetailView.bounds, // eventDetailView의 전체 크기를 기준으로
byRoundingCorners: [.topLeft, .bottomLeft], // 왼쪽 위/아래만 적용
cornerRadii: CGSize(width: 2, height: 2) // 반경 2 적용
)
// 3. CAShapeLayer를 생성하여 해당 경로를 마스크로 적용
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath.cgPath // UIBezierPath를 CGPath로 변환하여 적용
eventDetailView.layer.mask = maskLayer // 특정 영역만 보이도록 마스킹
}
배운 점
- 뷰의 Corner Radius 각각 다르게 처리하는 법을 배웠다.
- CACornerMask, UIBezierPath와 CAShapeLayer를 배웠다.
참조 링크
https://developer.apple.com/documentation/uikit/uibezierpath
https://developer.apple.com/documentation/quartzcore/cacornermask
https://develop-ssooo.tistory.com/175
https://stackoverflow.com/questions/46179735/round-top-corners-of-a-uiview-in-swift
'📱 iOS > UIKit' 카테고리의 다른 글
[문제해결] UITableViewCell 셀 내부 제스처가 스크롤을 막는 문제 해결: UIGestureRecognizerDelegate 활용 (0) | 2025.03.01 |
---|---|
[문제해결] UITableViewCell에서 CornerRadius 개별 설정 시 초기 레이아웃 문제를 비동기 재귀로 해결하기 (1) | 2025.02.28 |
[UIKit] UIMenu 사용기 (1) | 2024.12.10 |
[UIKit] CollectionViewCell 드래그 앤 드랍 구현하기 (0) | 2024.12.01 |
[UIKit] iOS 15.0 이상에서 UIButton 안에 있는 이미지 사이즈 조절하기 (3) | 2024.11.15 |