์๋ ํ์ธ์ Foma ๐ป ์ ๋๋ค!
ํ์์ AppStore๋ฅผ ๋ณด๋ฉด ํ๋ฉด ๊ฐ ์ ํํ ๋ ์์ฐ์ค๋ฌ์ด ์ ๋๋ฉ์ด์ ์ด ๋ง์ด ๋ณด์๋๋ฐ, '์ด๊ฑด ์ด๋ป๊ฒ ๊ตฌํํ์๊น' ๋ผ๋ ์๊ฐ์ด ๋ง์ด ๋ค์ด ๊ธ์ ์ ๋ฆฌํ๊ฒ ๋์์ต๋๋ค.
๋ฐ๋ก ์์ํ ๊ฒ์~
Preview
@Namespace
ํ๋ฉด ์ ํ ์ ๋๋ฉ์ด์ ์ ๊ตฌํํ๊ธฐ ์ํด์ @Namespace ํ๋กํผํฐ ๋ํผ๊ฐ ํ์ํฉ๋๋ค.
@Namespace๋ ๊ณต์ ๋ฌธ์์ ์๋์ ๊ฐ์ด ์๊ฐํฉ๋๋ค.
์์ฑ์ ํฌํจํ๋ ๊ฐ์ฒด(์: view)์ ์๊ตฌ ID๋ก ์ ์๋ ๋ค์์คํ์ด์ค์ ๋ํ ์ก์ธ์ค๋ฅผ ํ์ฉํ๋ ๋์ ์์ฑ ์ ํ์ ๋๋ค.
๊ฐ๋จํ๊ฒ ๋งํ๋ฉด ๊ฐ์ฒด์ ์ ๋ณด๋ฅผ ID์ ํจ๊ป ๊ธฐ์ตํ๊ณ ์๋ ๋ํผ์ ๋๋ค.
์ด ID๋ฅผ ํตํด์ ์ ๋ณด๋ฅผ ๋ค๋ฅธ ๋ทฐ์ ๊ณต์ ํ ์ ์์ผ๋ฉฐ, ์ด๊ฒ์ ํตํด ์ง์ค๋ฉํธ๋ฆฌ ์ ๋๋ฉ์ด์ ์ด ๊ฐ๋ฅํด ์ง๋๋ค.
์ ์ธํ๋ ๋ฐฉ์์ ์๋์ ๊ฐ์ด @Namespace๋ฅผ ๋ถ์ฌ์ฃผ๊ณ ๋ณ์์ ์ด๋ฆ์ ์ ํด์ค๋๋ค.
@Namespace var animation(์ํ๋ ์ด๋ฆ)
matchedGeometryEffect
matchedGeometryEffect๋ ์ํ๋ ID์ namespace๋ฅผ ์ด์ฉํ์ฌ ํน์ ๋ทฐ์ ์ง์ค๋ฉํธ๋ฆฌ ํจ๊ณผ๋ฅผ ๋ถ์ฌํ๋ ๋ฉ์๋์ ๋๋ค.
์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ์ด ์ํ๋ ๋ทฐ(๊ฐ์ฒด)์ id์ namespace๋ฅผ ํจ๊ป ์ ์ฉ์์ผ ์ค๋๋ค.
์ฃผ์ํ์ค ์ ์ ๋ฐ๋๋ ์ด๋ค ๊ฒ์ ์์ ์ ์ฉ์์ผ์ผ ํฉ๋๋ค.
์๋ ์ฝ๋์์ ํ๋ฉด์ ํ๋ ์์ ๋ฐ๊พธ๋ ๊ฒ์ด๋ฏ๋ก matchedGeometryEffect๋ฅผ frame์์ ์ ์ฉํ์ต๋๋ค.
Image("Highest in the room")
.resizable()
.aspectRatio(contentMode: .fill)
.clipShape(RoundedRectangle(cornerRadius: 15,style: .continuous))
.matchedGeometryEffect(id: "image", in:animation)
.frame(width: 150, height: 150)
GeometryView
๋ณธ๊ฒฉ์ ์ผ๋ก ํ๋ฉด ์ ํ ์ ๋๋ฉ์ด์ ์ฝ๋๋ฅผ ์์ฑํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
@State ๋ณ์๋ฅผ ์ด์ฉํ์ฌ ํ๋ฉด ์ ํ ์ ๋๋ฉ์ด์ ์ ์ ์ฉํ ์ ์๋๋ฐ์.
๋ํ ์ผ ํ๋ฉด์ ๋ณด์ฌ์ค ์ฌ๋ถ๋ฅผ ํ๋จํ ๋ณ์๋ฅผ ๋ง๋ค์ด ์ค๋๋ค.
@State var detailShow:Bool = false
body ๋ถ๋ถ์ ์๋์ ๊ฐ์ด detailShow๊ฐ true๋ผ๋ฉด DetailView๋ฅผ ์๋๋ผ๋ฉด ์๋์ ๊ฐ์ด Image๋ฅผ ๋์ธ ์ ์๋๋ก ํฉ๋๋ค.
๋ํ VStack์ onTapGesture๋ฅผ ์ ์ฉํ์ฌ VStack์ ๋๋ ์ ๋ ์ ๋๋ฉ์ด์ ๊ณผ ํจ๊ป detailShow ์ํ๊ฐ true๋ก ๋ณํ๋๋ก ํฉ๋๋ค.
var body: some View {
VStack {
if detailShow {
DetailView()
}else {
Image("Highest in the room")
.resizable()
.aspectRatio(contentMode: .fill)
.clipShape(RoundedRectangle(cornerRadius: 15,style: .continuous))
.matchedGeometryEffect(id: "image", in:animation)
.frame(width: 150, height: 150)
}
}
.onTapGesture {
withAnimation {
detailShow = true
}
}
}
DetailView
@ViewBuilder๋ฅผ ์ด์ฉํด DetailView๋ฅผ ๋ง๋ค์ด์ฃผ๊ณ Image์ ํฌ๊ธฐ์ ์์น๋ฅผ ์กฐ์ ํด ์ค๋๋ค.
Image์ ์ข์ธก ์๋จ์ ๋ค๋ก ๊ฐ๊ธฐ ์ด๋ฏธ์ง๋ฅผ ๋ฐฐ์นํ๊ณ , ํด๋น ์ด๋ฏธ์ง๋ฅผ ๋๋ฅด๋ฉด detailShow๊ฐ false๊ฐ ๋๋ฉฐ ์ด์ ํ๋ฉด์ผ๋ก ๋๋์ ๊ฐ ์ ์๋๋ก ํฉ๋๋ค.
@ViewBuilder
func DetailView() -> some View {
VStack {
Image("Highest in the room")
.resizable()
.aspectRatio(contentMode: .fill)
.clipShape(RoundedRectangle(cornerRadius: 15,style: .continuous))
.matchedGeometryEffect(id: "image", in:animation)
.frame(maxWidth: .infinity, maxHeight: 400)
.overlay {
VStack {
Image(systemName: "chevron.left")
.font(.title2)
.foregroundColor(.black)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top,30)
.padding(.leading,20)
.opacity(detailShow ? 1 : 0)
.onTapGesture {
withAnimation {
detailShow = false
}
}
Spacer()
}
}
Spacer()
}
.ignoresSafeArea(.all)
}
Test
์๋ GIF์ ๊ฐ์ด ์ ๋๋ฉ์ด์ ์ ํญํ๋ฉด ์์ฐ์ค๋ฝ๊ฒ ๋ํ ์ผ ํ๋ฉด์ผ๋ก ์ด๋ํ๊ฒ ๋๊ณ , ๋ํ ์ผ ํ๋ฉด์์ "<"๋ฅผ ๋๋ฅด๋ฉด ์ด์ ํ๋ฉด์ผ๋ก ๋์๊ฐ๊ฒ ๋ฉ๋๋ค.
์ค๋์ ์ด๋ ๊ฒ ์์ฐ์ค๋ฌ์ด ํ๋ฉด ์ ํ ์ ๋๋ฉ์ด์ ์ namespace์ matchedGeometryEffect๋ฅผ ์ด์ฉํ์ฌ ๊ตฌํํด ๋ณด์์ต๋๋ค.
ํน์๋ผ๋ ํ๋ฆฐ ์ ์ด ์๊ฑฐ๋ ๊ถ๊ธํ์ ์ ์ด ์๋ค๋ฉด ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์!
'๐ iOS > SwiftUI' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SwiftUI] GeometryReader๋? (feat. GeometryProxy,CoordinateSpace) (0) | 2022.04.04 |
---|---|
[SwiftUI] TabView์ ๋ํด ์์๋ณด๊ธฐ (feat. UITabBar) (0) | 2022.03.10 |
[SwiftUI] @State๋? (1) | 2021.11.07 |
๋๊ธ