Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
Tags
- Observer
- self
- ScrollView
- SWIFT
- CoreImage
- http
- escaping
- Git
- viewlifecycle
- Switch
- error
- array
- class
- uikit
- apns
- mvvm
- PushNotification
- 글또
- struct
- list
- SWIFTUI
- calendar
- 고차함수
- Animation
- 화면전환
- segue
- singleton
- Refresh
- IOS
- NotificationCenter
Archives
- Today
- Total
seong_hye, the developer
SwiftUI) matchedGeometryEffect에 대해 알아보기 본문
📘 matchedGeometryEffect
두 개 이상의 뷰를 같은 것으로 인식시켜서 레이아웃이 바뀔 떄 자연스럽게 이어지는 애니메이션을 만들어주는 도구
히어로 애니메이션 (Hero Animation) 이라고 불림
🔹개념
SwiftUI는 상태 변경 시 View를 새로 다시 그림
-> 일반적으로는 기본 뷰가 사라지고, 새로운 뷰가 나타나는 전환이 일어남
matchedGeometryEffect(id:in:)을 사용하면, 두 뷰를 같은 ID로 묶어서 SwiftUI가 "같은 요소"라고 인식
SwiftUI는 위치, 크기, 모양, 클리핑, 코너 반경 등을 자동으로 보간해줌
🔹문법
.matchedGeometryEffect(id: "sharedID", id: namespace)
id: 같은 그룹 안에서 고유하게 뷰를 매칭시킬 식별자
namespace: @Namespace로 선언하는 일종의 "애니메이션 공간"
🔹 기본 예제
🔍 탭 바 선택에 따라 선이 움직여지는 애니메이션
@Binding var currentTab: Int
@Namespace var namespace
var tabBarOptions: [String] = ["전체", "드라마", "영화", "애니메이션", "TV 프로그램", "스포츠"]
var body: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
ForEach(tabBarOptions.indices, id: \.self) { index in
Button {
currentTab = index
} label: {
VStack {
Spacer()
Text(tabBarOptions[index])
if currentTab == index {
Color.black
.frame(height: 2)
.matchedGeometryEffect(id: "titleLine", in: namespace)
} else {
Color.clear.frame(height: 2)
}
}
.animation(.spring(), value: currentTab)
}
.buttonStyle(.plain)
}
}
.padding(.horizontal)
}
.background(Color.white)
.frame(height: 40)
}
🔹 결과 화면
🔍 선택에 따라 원과 사각형이 바뀌는 애니메이션
VStack {
if show {
Spacer()
RoundedRectangle(cornerRadius: 50.0)
.matchedGeometryEffect(id: "circle", in: namespace)
.frame(minWidth: 0, maxWidth: .infinity, maxHeight: 300)
.padding()
.foregroundColor(Color(.systemGreen))
.onTapGesture {
withAnimation(.smooth) { show.toggle() }
}
} else {
RoundedRectangle(cornerRadius: 50.0)
.matchedGeometryEffect(id: "circle", in: namespace)
.frame(width: 100, height: 100)
.foregroundColor(Color(.systemOrange))
.onTapGesture {
withAnimation(.smooth) { show.toggle() }
}
Spacer()
}
}
🔹 결과 화면
🔹특징
양방향 매칭 (if / else 구조에서 서로 다른 뷰라도 같은 ID와 namespace면 이어짐)
위치, 크기, 코너 반경, 클리핑, 그림자 등이 자동 보간
같은 ID를 여러 개 두면 SwiftUI가 혼란스러워함 -> 하나씩만 매칭
transition과 함께 쓰면 더 자연스러움
🔹한계 / 주의사항
스크롤 뷰 안에서는 애니메이션이 어색할 수 있음 (좌표계 이슈)
동시에 두 개의 뷰가 존재하면 SwiftUI가 어떤 걸 연결할지 헷갈림
이펙트는 단일 namespace 내에서만 유효
복잡한 레이아웃(그리드, 리스트)에선 .zIndex를 적절히 설정해야 깜빡임 방지
'IOS > SwiftUI' 카테고리의 다른 글
SwiftUI) Path에 대해 알아보기 (0) | 2025.07.21 |
---|---|
SwiftUI) 이미지(사진) 권한 설정에 대해 알아보기 (0) | 2025.07.15 |
SwiftUI) Transition, Animation에 대해 알아보기 (0) | 2024.10.16 |
SwiftUI) 어플 자동 업데이트 기능에 대해 정리하기 (0) | 2024.03.27 |
Swift) List 내용 삭제될 경우 기본 선택 값 변경되도록 제작하기 (0) | 2023.10.31 |
Comments