Published on

SwiftUI-da Popover modifier — native popover yaratish (iOS 16.4+)

Authors

Bu videoda biz Popover modifier-ni ko'rib chiqamiz. Avvalroq "popover boot camp" videosida sheet va transition yordamida o'zimiz yasagan edik — bu safar esa iOS 16.4 da kelgan native SwiftUI versiyasini ko'ramiz.

Popover — foydalanuvchiga kichik ma'lumot, menyu yoki maslahat ko'rsatishning eng qulay usuli. Sheet va FullScreenCover-dan farqi: butun ekranni qoplamaydi, tugma yonida paydo bo'ladi.


Boshlang'ich sozlama

struct NativePopoverBootcamp: View {

    @State private var showPopover: Bool = false

    var body: some View {
        ZStack {
            Color.gray
                .ignoresSafeArea()

            Button("Bosing") {
                showPopover.toggle()
            }
            .popover(isPresented: $showPopover) {
                Text("Salom!")
            }
        }
    }
}

Bu kodni ishlatganda — sheet chiqadi, popover emas! Nima uchun?


presentationCompactAdaptation — popover ko'rinishi uchun shart

iPhone-da popover standart holatda sheet kabi ko'rinadi. Haqiqiy popover ko'rinishi uchun yangi modifier kerak:

Button("Bosing") {
    showPopover.toggle()
}
.popover(isPresented: $showPopover) {
    Text("Salom!")
        // ✅ Bu modifier bo'lmasa sheet ko'rinadi
        .presentationCompactAdaptation(.popover)
}

Eslatma: presentationCompactAdaptation — iOS 16.4 dan boshlab mavjud. Loyihangizning minimal iOS versiyasini 16.4 ga o'rnating.


Adaptatsiya turlari

// Standart sheet ko'rinishi
.presentationCompactAdaptation(.sheet)

// To'liq ekran
.presentationCompactAdaptation(.fullScreenCover)

// Haqiqiy popover — tugma yonida paydo bo'ladi
.presentationCompactAdaptation(.popover)

Apple bu modifier orqali kelajakda sheet va fullScreenCover-ni ham shu usulga o'tkazishini ko'rsatyapti. Shuning uchun .popover modifier-ini avvaldan o'rganib qo'ygan ma'qul.


Popover qayerda paydo bo'ladi?

Popover — modifier qo'yilgan view-ning tepasida paydo bo'ladi. Shuning uchun modifier tugmaga qo'yish kerak, katta container-ga emas:

// ❌ NOTO'G'RI — ZStack-ga qo'yilgan, popover ekran burchagida paydo bo'ladi
ZStack {
    Color.gray.ignoresSafeArea()
    Button("Bosing") { showPopover.toggle() }
}
.popover(isPresented: $showPopover) { ... }

// ✅ TO'G'RI — tugmaga qo'yilgan, popover tugma yonida paydo bo'ladi
ZStack {
    Color.gray.ignoresSafeArea()
    Button("Bosing") { showPopover.toggle() }
        .popover(isPresented: $showPopover) { ... }
}

attachmentAnchor — aniqroq joylashuv sozlash

Button("Bosing") {
    showPopover.toggle()
}
.padding()
.background(Color.yellow)
.popover(
    isPresented: $showPopover,
    attachmentAnchor: .point(.top),   // tugmaning qaysi nuqtasidan
    arrowEdge: .bottom                // macOS uchun, iOS-da ta'sir qilmaydi
) {
    Text("Popover mazmuni")
        .padding(20)
        .presentationCompactAdaptation(.popover)
}

attachmentAnchor turlari:

.point(.center)      // tugma markazidan
.point(.top)         // tugma yuqorisidan — popover tepada paydo bo'ladi
.point(.bottom)      // tugma pastidan — popover pastda paydo bo'ladi
.point(.topLeading)  // tugmaning yuqori-chap burchagidan

Apple-ning avtomatik ekran logikasi

Popover joylashuvi avtomatik boshqariladi — ekrandan chiqmaydi:

VStack {
    // Tugma ekranning YUQORISIDA bo'lsa
    Button("Yuqoridagi tugma") { showPopover.toggle() }
        .popover(isPresented: $showPopover) { ... }
    // → Popover PASTDA paydo bo'ladi

    Spacer()
}

VStack {
    Spacer()
    // Tugma ekranning PASTIDA bo'lsa
    Button("Pastdagi tugma") { showPopover.toggle() }
        .popover(isPresented: $showPopover) { ... }
    // → Popover YUQORIDA paydo bo'ladi
}

Bu Apple-ning avtomatik UX logikasi — popover hech qachon ekrandan tashqariga chiqmaydi. Siz attachment anchor-ni belgilaysiz, Apple esa eng qulay joyni tanlaydi.


Tashqarini bosish bilan yopish

Sheet-dan farqli ravishda, popover-ni yopish uchun faqat ekranning istalgan joyini bosish yetarli — alohida "Yopish" tugmasi kerak emas:

// Sheet — dismiss uchun kod kerak
@Environment(\.presentationMode) var presentationMode
presentationMode.wrappedValue.dismiss()

// Popover — ekranning istalgan joyini bosish yopadi, kod kerak emas

Haqiqiy dunyo misoli — feedback menyu

struct NativePopoverBootcamp: View {

    @State private var showPopover: Bool = false
    @State private var feedbackOptions: [String] = [
        "Juda yaxshi 😊",
        "O'rtacha 🙂",
        "Yomon 😡"
    ]

    var body: some View {
        VStack {
            Spacer()

            Button("Fikr bildiring") {
                showPopover.toggle()
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(10)
            .popover(isPresented: $showPopover) {
                VStack(alignment: .leading, spacing: 12) {
                    ForEach(feedbackOptions, id: \.self) { option in
                        Button(option) {
                            // Fikr tanlandi
                            showPopover = false
                        }

                        // Oxirgi element bundan tashqari divider
                        if option != feedbackOptions.last {
                            Divider()
                        }
                    }
                }
                .padding(20)
                .presentationCompactAdaptation(.popover)
            }
        }
    }
}

Ko'p variant bo'lsa ScrollView ichiga ham solish mumkin:

.popover(isPresented: $showPopover) {
    ScrollView {
        VStack(alignment: .leading, spacing: 12) {
            ForEach(feedbackOptions, id: \.self) { option in
                Button(option) { showPopover = false }
                Divider()
            }
        }
        .padding(20)
    }
    .presentationCompactAdaptation(.popover)
}

Sheet, FullScreenCover va Popover taqqoslash

SheetFullScreenCoverPopover
Ko'rinishPastdan chiqadiTo'liq ekranTugma yonida
YopishPastga surishKod bilanIstalgan joy
HajmiKattaTo'liqKichik
QachonYangi ekranTo'liq o'tishKichik info/menyu
iOS versiyaBarchaBarcha16.4+

Xulosa

Button("Menyu") {
    showPopover.toggle()
}
.popover(isPresented: $showPopover) {
    // kontent
    .presentationCompactAdaptation(.popover)  // ← shart!
}

Popover — kichik maslahat, menyu yoki tugmachalar to'plamini ko'rsatish uchun ideal. Sheet-dan ko'ra ancha yengil va foydalanuvchi uchun qulayroq. Ekranning istalgan joyini bosib yopilishi katta UX afzalligi.

Buy mea coffee