MatchedGeometryEffect (MatchedGeometryEffect)
«اثر تطبیق هندسه (MatchedGeometryEffect)» یعنی حفظ هویت دید بین چیدمان ها. وقتی نما جابه جا شود، مسیر حرکتش نرم می شود. مثل کارت که باز می شود و به صفحه جزئیات می رسد.
ایده اصلی اثر تطبیق هندسه
به دو نما یک شناسه مشترک بده. سپس SwiftUI اندازه و موقعیت را بین آن ها انیمیت می کند. برای اجرا، تغییر state را با withAnimation انجام بده.
نکته: نام فضا یا Namespace برای گروه بندی شناسه هاست. این کمک می کند انیمیشن ها اشتباه قاطی نشوند.
سینتکس پایه
روی هر دو نما بنویس: .matchedGeometryEffect(id: "id", in: namespace). هر دو باید دقیقاً همان id داشته باشند.
مثال 1: نقطه به دایره بزرگ
دو دایره یک شناسه مشترک دارند. با تغییر state، اندازه و موقعیت نرم جابه جا می شود.
import SwiftUI
struct MatchedDemo: View {
@Namespace private var ns
@State private var showDetail = false
var body: some View {
VStack(spacing: 16) {
if showDetail {
Circle()
.matchedGeometryEffect(id: "dot", in: ns)
.frame(width: 120, height: 120)
} else {
Circle()
.matchedGeometryEffect(id: "dot", in: ns)
.frame(width: 40, height: 40)
}
Button("Toggle") {
withAnimation(.spring()) {
showDetail.toggle()
}
}
}
.padding()
}
}
struct ContentView: View {
var body: some View {
MatchedDemo()
}
}
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
شناسه مشترک «dot» باعث پیوستگی دیداری می شود. چشم مسیر را راحت دنبال می کند.
مثال 2: کارت به صفحه جزئیات
کارت کوچک با همان شناسه به کارت بزرگ تبدیل می شود. متن روی کارت نیز هماهنگ می ماند.
import SwiftUI
struct CardsMatchedDemo: View {
@Namespace private var ns
@State private var expanded = false
var body: some View {
VStack(spacing: 16) {
if expanded {
RoundedRectangle(cornerRadius: 16)
.fill(Color.blue.opacity(0.2))
.matchedGeometryEffect(id: "card", in: ns)
.frame(height: 160)
.overlay(
Text("Detail")
.font(.headline)
)
} else {
RoundedRectangle(cornerRadius: 12)
.fill(Color.blue.opacity(0.2))
.matchedGeometryEffect(id: "card", in: ns)
.frame(height: 60)
.overlay(
Text("Card")
.font(.subheadline)
)
}
Button(expanded ? "Close" : "Open") {
withAnimation(.spring()) {
expanded.toggle()
}
}
}
.padding()
}
}
struct ContentView: View {
var body: some View {
CardsMatchedDemo()
}
}
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
این تکنیک پیوستگی بصری را حفظ می کند. بنابراین تجربه کاربر طبیعی تر می شود.
گام های عملی شروع سریع
- یک @Namespace تعریف کن.
- برای دو نما،
idمشترک بگذار. - تغییر state را داخل
withAnimation(...)انجام بده.
نکته: برای ورود و خروج، از ترنزیشن ها کمک بگیر. برای تنظیم فنر، به انیمیشن فنری سر بزن. همچنین راهنمای کلی انیمیشن SwiftUI را ببین. برای جزئیات همین موضوع، اثر تطبیق هندسه را مرجع کن.
جمع بندی سریع
- دو نما، یک شناسه مشترک داشته باشند.
- چیدمان ها باهم پیوند می خورند.
- حرکت ها نرم و طبیعی می شوند.
- با
withAnimationاجرا را کنترل کن.