- Published on
SwiftUI-da o'lchamini o'zgartirib bo'ladigan Sheet yaratish (iOS 16+)
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Bu iOS 16 da chiqqan eng yaxshi yangiliklar ichida birinchi o'rinda turadi. Avval sheet faqat ekranning yuqorisiga qadar ochilardi — yarim ekran, chorak ekran sheet yaratish mumkin emas edi. iOS 16 dan boshlab bu butunlay o'zgardi.
Eng yaxshi tomoni — mavjud sheet kodi o'zgarmaydi. Shunchaki bitta yangi modifier qo'shiladi va sheet istalgan o'lchamga ega bo'ladi.
Boshlang'ich sozlama
struct ResizableSheetBootcamp: View {
@State private var showSheet: Bool = false
var body: some View {
Button("Bosing") {
showSheet.toggle()
}
.sheet(isPresented: $showSheet) {
MyNextView()
}
}
}
struct MyNextView: View {
var body: some View {
Color.red
.ignoresSafeArea()
}
}
Standart sheet ekranning taxminan 90% ini qoplaydi. iOS 16 gacha yarim ekran sheet yaratish uchun murakkab drag gesture-larni qo'lda kodlash kerak edi.
presentationDetents — sheet o'lchamini belgilash
.sheet(isPresented: $showSheet) {
MyNextView()
.presentationDetents([.medium]) // yarim ekran
}
Detent — sheet keta oladigan o'lcham nuqtasi.
Tayyor detent-lar
// Katta — standart sheet o'lchami (90% ekran)
.presentationDetents([.large])
// O'rta — aynan 50% ekran
.presentationDetents([.medium])
Bir nechta detent — drag bilan o'tish
Bir nechta detent qo'shilsa, foydalanuvchi sheet-ni ular orasida sudrab o'tkaza oladi:
.sheet(isPresented: $showSheet) {
MyNextView()
.presentationDetents([.medium, .large])
// Foydalanuvchi medium va large orasida sudrab o'tkazishi mumkin
}
Bir nechta detent bo'lganda avtomatik drag indikatori (kichik chiziqcha) paydo bo'ladi. Uni yashirish mumkin:
.presentationDetents([.medium, .large])
.presentationDragIndicatorHidden(true) // indikatorni yashirish
// Lekin drag imkon bo'lsa ko'rsatib qo'yish yaxshiroq
Maxsus o'lchamlar — fraction va height
fraction — ekran ulushi
.presentationDetents([.fraction(0.1)]) // 10% — ekran pastida kichik panel
.presentationDetents([.fraction(0.5)]) // 50% — medium ga o'xshash
.presentationDetents([.fraction(0.75)]) // 75%
.presentationDetents([.fraction(0.9)]) // 90% — large ga o'xshash
height — aniq piksel
.presentationDetents([.height(200)]) // 200 piksel
.presentationDetents([.height(500)]) // 500 piksel
.presentationDetents([.height(800)]) // 800 piksel
Eslatma: height ishlatganda turli qurilmalarda ekran balandligi farq qilishini yodda tuting. fraction ko'proq xavfsiz — har qanday qurilmada to'g'ri ko'rinadi.
Bir nechta maxsus detent-larni birlashtirish
.sheet(isPresented: $showSheet) {
MyNextView()
.presentationDetents([
.fraction(0.1), // 10% — kichik pastki panel
.medium, // 50% — o'rta
.height(600), // 600 piksel
.large // to'liq
])
}
Foydalanuvchi bu to'rtta nuqta orasida sheet-ni sudrab o'tkaza oladi. Ilova ochilganda kichik panel ko'rinadi, foydalanuvchi xohlagancha kattalashtirishi mumkin.
interactiveDismissDisabled — yopishni bloklash
Foydalanuvchi sheet-ni pastga sudrab yopa olmasligi uchun:
.sheet(isPresented: $showSheet) {
MyNextView()
.presentationDetents([.medium])
.interactiveDismissDisabled(true) // yopib bo'lmaydi
}
Qachon kerak:
- To'lov ekrani — foydalanuvchi to'lovni amalga oshirmasdan yopa olmasin
- Onboarding — barcha qadamlar bajarilmaguncha yopilmasin
- Muhim ruxsat so'rovi — foydalanuvchi qaror qilishi shart
@Binding bilan programmatik boshqarish
Kod orqali sheet o'lchamini o'zgartirish — masalan, tugma bosilganda:
struct ResizableSheetBootcamp: View {
@State private var showSheet: Bool = false
@State private var selectedDetent: PresentationDetent = .large
var body: some View {
Button("Bosing") {
showSheet.toggle()
}
.sheet(isPresented: $showSheet) {
MyNextView(selectedDetent: $selectedDetent)
.presentationDetents(
[.medium, .large],
selection: $selectedDetent // binding
)
}
}
}
struct MyNextView: View {
@Binding var selectedDetent: PresentationDetent
var body: some View {
VStack(spacing: 20) {
Button("O'rta o'lcham") {
selectedDetent = .medium // programmatik o'zgartirish
}
Button("Katta o'lcham") {
selectedDetent = .large
}
}
}
}
Muhim: Programmatik tarzda o'rnatilayotgan detent presentationDetents([...]) ichida ham ko'rsatilgan bo'lishi shart. Aks holda ishlaydi, lekin to'g'ri o'lchamga o'tmaydi.
// ❌ NOTO'G'RI — .fraction(0.5) ro'yxatda yo'q
.presentationDetents([.medium, .large], selection: $selectedDetent)
selectedDetent = .fraction(0.5) // ishlaydi, lekin o'tmaydi
// ✅ TO'G'RI — ro'yxatda ham bor
.presentationDetents([.medium, .large, .fraction(0.5)], selection: $selectedDetent)
selectedDetent = .fraction(0.5) // to'g'ri ishlaydi
To'liq misol
struct ResizableSheetBootcamp: View {
@State private var showSheet: Bool = false
@State private var selectedDetent: PresentationDetent = .large
var body: some View {
Button("Bosing") {
showSheet.toggle()
}
.sheet(isPresented: $showSheet) {
MyNextView(selectedDetent: $selectedDetent)
.presentationDetents(
[.fraction(0.2), .medium, .height(600), .large],
selection: $selectedDetent
)
.presentationDragIndicatorHidden(false)
}
}
}
struct MyNextView: View {
@Binding var selectedDetent: PresentationDetent
var body: some View {
VStack(spacing: 20) {
Text("Salom dunyo!")
.font(.headline)
Button("20%") {
selectedDetent = .fraction(0.2)
}
Button("O'rta (50%)") {
selectedDetent = .medium
}
Button("600 piksel") {
selectedDetent = .height(600)
}
Button("Katta (to'liq)") {
selectedDetent = .large
}
}
.padding()
}
}
Xulosa
| Detent | Yozilishi | Natija |
|---|---|---|
| Katta | .large | ~90% ekran |
| O'rta | .medium | ~50% ekran |
| Ulush | .fraction(0.3) | 30% ekran |
| Balandlik | .height(300) | 300 piksel |
| Bir nechta | [.medium, .large] | Drag bilan o'tish |
iOS 16 dan oldin yarim ekran sheet yasash uchun drag gesture-larni qo'lda kodlash kerak edi — bu juda ko'p ish edi. Endi bitta .presentationDetents([.medium]) — va tayyor. Bu iOS 16 ning eng foydali API-laridan biri.
Rahmat, men Nick, bu Swiftful Thinking va keyingi videoda ko'rishguncha!