Published on

SwiftUI'da MatchedGeometryEffect bilan ishlash

Authors

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:

  1. @Namespace o'zgaruvchisi (O'zaro bog'lanuvchi elementlar maydoni)
  2. Bir xil id raqamiga 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: .matchedGeometryEffect asosan to'g'ri shakllar (Rectangle, Circle, Capsule) bilan ajoyib va muammosiz ishlaydi. Uni Text kabi ma'lumotlar bilan ishlatishda kutilmagan miltillash va xatolar paydo bo'lishi mumkin.

Buy mea coffee