- Published on
SwiftUI'da MatchedGeometryEffect bilan ishlash
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
MatchedGeometryEffect o'zi nima?
Ushbu modifikator asosan shakllarning o'lchami va joylashuvini ekranda silliq o'zgartirish (morphing) uchun ishlatiladi. Bu shunday ishlaydiki: ekranda birinchi shakl paydo bo'ladi. Keyin u yo'qolib, o'rniga ikkinchi shakl paydo bo'ladi. Biz tizimga ushbu ikki xil shakl aslida "Bitta narsa" ekanligini aytamiz va tizim ularning o'rnashuviga qarab chiroyli animatsiyani avtomatik ulab beradi.
Buning uchun bizga faqat ikkita narsa kerak:
@Namespaceo'zgaruvchisi (O'zaro bog'lanuvchi elementlar maydoni)- Bir xil
idraqamiga ega bo'lgan.matchedGeometryEffect()modifikatori.
Asosiy misol: Shaklni ekranda ko'chirish
Tasavvur qiling, ekranning tepasida turgan kichik to'rtburchak pastga siljib, kattaroq to'rtburchakka aylanadi.
import SwiftUI
struct MatchedGeometryEffectBootcamp: View {
@State private var isClicked: Bool = false
@Namespace private var namespace // 1. Namespace e'lon qilamiz
var body: some View {
VStack {
if !isClicked {
// Tepedagi kichik shakl
RoundedRectangle(cornerRadius: 25)
// Modifikator frame() dan oldin yozilishi tavsiya etiladi
.matchedGeometryEffect(id: "rectangle", in: namespace)
.frame(width: 100, height: 100)
}
Spacer()
if isClicked {
// Pastdagi kattaroq shakl
RoundedRectangle(cornerRadius: 25)
// ID va Namespace huddi o'sha!
.matchedGeometryEffect(id: "rectangle", in: namespace)
.frame(width: 300, height: 200)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red.opacity(0.2))
.onTapGesture {
withAnimation(.easeInOut) {
isClicked.toggle()
}
}
}
}
E'tibor bergan bo'lsangiz biz qo'lda offset bilan siljitmadik. Tizim shunchaki "Tepadagi tortburchak ekrandan ketyapti va uning id'si pastda paydo bo'lyapti" deb uni darhol o'zi tushirib beradi.
Real loyihalardagi ko'rinishi: custom tab bar / kategoriyalar
Aksariyat ilovalarda "Home", "Popular", "Saved" kabi filtlar ro'yxati (Segmented Control) bo'ladi. Tanlanganini ko'rsatib turish uchun uning orqasiga yorliq (yoki tagiga chiziq) qo'yiladi. matchedGeometryEffect aynan shu yerdagi animatsiyada juda ajoyib natija ko'rsatadi:
struct MatchedGeometryEffectExample2: View {
let categories: [String] = ["Home", "Popular", "Saved"]
@State private var selected: String = ""
@Namespace private var namespace2
var body: some View {
HStack {
ForEach(categories, id: \.self) { category in
ZStack(alignment: .bottom) {
// Agar aynan shu element tanlangan bo'lsa, chiziqcha qo'shiladi
if selected == category {
RoundedRectangle(cornerRadius: 10)
.fill(Color.red)
// Ularning barchasi bitta id ("category_background") dan foydalanmoqda
.matchedGeometryEffect(id: "category_background", in: namespace2)
.frame(width: 35, height: 2)
.offset(y: 10)
}
Text(category)
.foregroundColor(selected == category ? .red : .black)
}
.frame(maxWidth: .infinity)
.frame(height: 55)
.onTapGesture {
withAnimation(.spring()) {
selected = category
}
}
}
}
.padding()
}
}
Bu yerda biz bitta id ni butun tsiklga (ForEach) ishlatyapmiz, chunki if selected == category orqali butun ro'yxatdan doimo faqatgina bittasi haqiqatda chiziladi. Tugmalarni bosganda selected o'zgaradi va tizim shu joydagi chiziqchani endi boshqa joydagi yangi tugmaga ajoyib sirpanish (spring) bilan olib boradi!
Qoida:
.matchedGeometryEffectasosan to'g'ri shakllar (Rectangle,Circle,Capsule) bilan ajoyib va muammosiz ishlaydi. UniTextkabi ma'lumotlar bilan ishlatishda kutilmagan miltillash va xatolar paydo bo'lishi mumkin.