[UIKit] 뷰의 Corner Radius 각각 다르게 처리하기 (with CACornerMask, UIBezierPath, CAShapeLayer)

2025. 2. 28. 20:37·📱 iOS/UIKit

학습 개요

디자인 요구사항에 따라 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 안에 있는 이미지 사이즈 조절하기  (4) 2024.11.15
'📱 iOS/UIKit' 카테고리의 다른 글
  • [문제해결] UITableViewCell 셀 내부 제스처가 스크롤을 막는 문제 해결: UIGestureRecognizerDelegate 활용
  • [문제해결] UITableViewCell에서 CornerRadius 개별 설정 시 초기 레이아웃 문제를 비동기 재귀로 해결하기
  • [UIKit] UIMenu 사용기
  • [UIKit] CollectionViewCell 드래그 앤 드랍 구현하기
kyxxn
kyxxn
컴퓨터공학을 좋아하는 대학생의 공부 일기
  • kyxxn
    컴공 학부생의 공부 일기
    kyxxn
  • 전체
    오늘
    어제
    • 분류 전체보기 (156)
      • 📱 iOS (64)
        • Xcode (10)
        • Swift (17)
        • Swift Concurrency (12)
        • UIKit (21)
        • SwiftUI (0)
      • 🖥️ Computer Science (57)
        • 🏛️ Software Architecture Pa.. (2)
        • 👨🏻‍🎨 Design Pattern (3)
        • Data Structure (4)
        • Algorithm (10)
        • Computer Architecture (4)
        • Operating System (19)
        • Network (15)
      • ✍🏻 회고록 (9)
      • 🎸 기타 (25)
        • 해커톤 (1)
        • git (6)
        • 세미나 (1)
        • 책을 읽고 (1)
        • AOS, Kotlin (6)
        • Reinforcement Learning (9)
  • 블로그 메뉴

    • 링크

      • 깃허브
      • 일상 블로그
    • 공지사항

    • 인기 글

    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.0
    kyxxn
    [UIKit] 뷰의 Corner Radius 각각 다르게 처리하기 (with CACornerMask, UIBezierPath, CAShapeLayer)
    상단으로

    티스토리툴바