Published on

SwiftUI-da LongPressGesture-dan qanday foydalanish kerak

Authors

LongPressGesture nima

LongPressGesture β€” tap gesture-ga o'xshash ishlaydi, lekin farqi shunda: tap gesture-da amal darhol bajariladi, LongPressGesture-da esa foydalanuvchi ma'lum muddat bosib ushlab turishi kerak β€” shundagina amal bajariladi.


Yangi fayl yaratish

Xcode-da yangi SwiftUI View fayl yaratamiz β€” LongPressGestureBootcamp deb nomlaymiz.


Oddiy misol

Avval oddiy holatdan boshlaymiz:

@State private var isComplete: Bool = false

var body: some View {
    Text(isComplete ? "Completed" : "Not Complete")
        .padding()
        .padding(.horizontal)
        .background(isComplete ? Color.green : Color.gray)
        .cornerRadius(10)
        .onTapGesture {
            isComplete.toggle()
        }
}

Bu β€” oddiy tap gesture. Bosgan zahoti o'zgaradi.

.onLongPressGesture qo'shish

Endi tap gesture o'rniga long press ishlatamiz:

.onLongPressGesture {
    isComplete.toggle()
}

Endi tez bosish ishlam aydi β€” foydalanuvchi taxminan 1 soniya bosib ushlab turishi kerak.

minimumDuration parametri

.onLongPressGesture(minimumDuration: 1.0) {
    isComplete.toggle()
}
  • minimumDuration: 1.0 β€” kamida 1 soniya bosib turish kerak
  • minimumDuration: 5.0 β€” kamida 5 soniya bosib turish kerak

maximumDistance parametri

.onLongPressGesture(minimumDuration: 1.0, maximumDistance: 50) {
    isComplete.toggle()
}

maximumDistance β€” foydalanuvchi barmog'ini qancha uzoqqa siljitishi mumkinligini belgilaydi. Agar bu chegaradan oshsa, long press bekor qilinadi.

  • maximumDistance: 1 β€” barmoq deyarli qimirlamasa ishlaydi
  • maximumDistance: 50 β€” 50 pointgacha harakat qilsa ham ishlaydi

Bu parametr, ayniqsa, bosilishi qiyin yoki kichik elementlar uchun foydali.


Amaliy misol: yuklash paneli (loading bar)

Endi haqiqiy ilovada ishlatilishi mumkin bo'lgan misolni ko'rib chiqamiz β€” foydalanuvchi element ustida 1 soniya bosib ushlab turganda, animatsiya bilan "yuklash" bajariladi va rang yashilga o'zgaradi.

State o'zgaruvchilar

@State private var isComplete: Bool = false
@State private var isSuccess: Bool = false

View tuzilmasi

var body: some View {
    VStack(spacing: 20) {
        // Yuklash paneli
        Rectangle()
            .fill(isSuccess ? Color.green : Color.blue)
            .frame(maxWidth: isComplete ? .infinity : 0, alignment: .leading)
            .frame(maxWidth: .infinity, alignment: .leading)
            .frame(height: 55)
            .background(Color.gray)

        HStack {
            // Click tugmasi
            Text("Click here")
                .foregroundColor(.white)
                .padding()
                .background(Color.black)
                .cornerRadius(10)
                .onLongPressGesture(
                    minimumDuration: 1.0,
                    maximumDistance: 50,
                    pressing: { isPressing in
                        if isPressing {
                            withAnimation(.easeInOut(duration: 1.0)) {
                                isComplete = true
                            }
                        } else {
                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                                if !isSuccess {
                                    withAnimation(.easeInOut) {
                                        isComplete = false
                                    }
                                }
                            }
                        }
                    },
                    perform: {
                        withAnimation(.easeInOut) {
                            isSuccess = true
                        }
                    }
                )

            // Reset tugmasi
            Text("Reset")
                .foregroundColor(.white)
                .padding()
                .background(Color.black)
                .cornerRadius(10)
                .onTapGesture {
                    isComplete = false
                    isSuccess = false
                }
        }
    }
}

pressing va perform closure-larini tushuntirish

.onLongPressGesture(
    minimumDuration: 1.0,
    maximumDistance: 50,
    pressing: { isPressing in
        // Bu closure IKKI MARTA chaqiriladi:
        // 1. Bosish boshlanida: isPressing = true
        // 2. Qo'l ko'tarilganda: isPressing = false
    },
    perform: {
        // Bu closure minimumDuration tugaganda chaqiriladi
        // Ya'ni 1 soniyadan so'ng
    }
)

Logika

HolatNima sodir bo'ladi
Bosish boshlanadi (isPressing = true)isComplete = true β€” animatsiya boshlanadi
minimumDuration tugadi (perform)isSuccess = true β€” rang yashilga o'zgaradi
Qo'l ko'tariladi, lekin 1 soniya bo'lmadiisComplete = false β€” animatsiya orqaga qaytadi
Qo'l ko'tariladi, 1 soniya bo'ldiisSuccess = true bo'lgani uchun β€” qoldiradi

Nima uchun DispatchQueue kerak

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
    if !isSuccess {
        withAnimation(.easeInOut) {
            isComplete = false
        }
    }
}

pressing closure-i (isPressing = false) va perform closure-i deyarli bir vaqtda chaqirilishi mumkin. Agar 0.1 soniyalik kechiktirishsiz isComplete = false deb qo'ysak, perform ichidagi isSuccess = true dan oldin bajarilishi mumkin β€” bu esa animatsiyaning noto'g'ri qaytishiga olib keladi.

Kechiktirishda biz avval isSuccess o'rnatilishiga imkon beramiz, so'ngra tekshiramiz.


Natija

HarakatNatija
Tez bosishHech narsa bo'lmaydi
Bosib ushlab turish (< 1 soniya)Animatsiya boshlanadi, qo'l ko'tarilganda orqaga qaytadi
Bosib ushlab turish (= 1 soniya)Animatsiya to'liq bajariladi, rang yashilga o'zgaradi
"Reset" bosishHammasi boshlang'ich holatga qaytadi

Qachon ishlatiladi

LongPressGesture ko'p ilovada keng tarqalgan emas β€” asosan o'yinlarda ishlatiladi, masalan, bir necha soniya ushlab turganda ball olish yoki mukofot berish. Ammo ba'zi ilovalarda ham foydali bo'lishi mumkin: element ustida ushlab turish orqali qo'shimcha animatsiya boshlanadi va so'ngra boshqa ekranga o'tish kabi holatlar.

Buy mea coffee