Published on

SwiftUI-da NavigationSplitView

Authors

NavigationView va NavigationStack bitta ekrandan ikkinchisiga o'tish uchun ishlatiladi β€” yangi ekran joriy ekranni almashtiradi. NavigationSplitView esa bir vaqtning o'zida bir nechta ustun (odatda ikki yoki uchta) ko'rsatish imkonini beradi.

Bu komponent asosan iPad, Mac va kelajakda visionOS ilovalari uchun mo'ljallangan. iPhone-da odatda kerak bo'lmaydi, chunki ekran joyi cheklangan.


Yangi fayl yaratish

Navigatorda o'ng tugma bosib yangi SwiftUI fayli yarating. Uni NavigationSplitViewBootcamp deb nomlang va Create tugmasini bosing.


Ikki ustunli oddiy misol

struct NavigationSplitViewBootcamp: View {
    var body: some View {
        NavigationSplitView {
            Color.red
        } detail: {
            Color.blue
        }
    }
}
  • Birinchi closure β€” sidebar (yon menyu)
  • detail β€” asosiy kontent

iPhone simulyatorida faqat birinchi ekran ko'rinadi. NavigationSplitView iPhone va iPad-da turlicha ishlaydi β€” iPad-da yon menyu va kontent yonma-yon ko'rinadi, iPhone-da esa odatdagi navigatsiyaga o'xshab ishlaydi.

iPad simulyatorida ko'rsangiz, yuqori chap burchakda menyu tugmasi paydo bo'ladi β€” u sidebar (qizil qism) ni ochadi.


Uch ustunli misol

struct NavigationSplitViewBootcamp: View {
    var body: some View {
        NavigationSplitView {
            Color.red
        } content: {
            Color.blue
        } detail: {
            Color.green
        }
    }
}

Uchta qism:

  • sidebar β€” birinchi closure (qizil)
  • content β€” ikkinchi qism (ko'k)
  • detail β€” asosiy ekran (yashil)

iPad-da bu uch darajali navigatsiyani hosil qiladi: sidebar β†’ content β†’ detail.


columnVisibility β€” boshlang'ich holatni boshqarish

NavigationSplitView qaysi ustunlar boshida ko'rinishini sozlash mumkin:

struct NavigationSplitViewBootcamp: View {

    @State private var visibility: NavigationSplitViewVisibility = .automatic

    var body: some View {
        NavigationSplitView(columnVisibility: $visibility) {
            Color.red
        } detail: {
            Color.blue
        }
    }
}

Mumkin bo'lgan qiymatlar

QiymatMa'no
.automaticTizim qurilma va yo'nalishga qarab o'zi qaror qiladi
.doubleColumnBoshida ikkala ustun ham ko'rinadi
.detailOnlyBoshida faqat detail ekran ko'rinadi

Diqqat: bu faqat ikki ustunli (sidebar + detail) holat uchun ishlaydi. Uch ustunli versiyada hozircha to'liq uch ustunni bir vaqtda majburlash imkoni yo'q.

@State ishlatilishining sababi β€” foydalanuvchi ustunlar orasida bosib yurganda holat o'zgarib turadi, shuning uchun bog'lanish (binding) kerak.


NavigationSplitView {
    Color.red
} detail: {
    Color.blue
}
.navigationSplitViewStyle(.balanced)

Stillarni solishtirish

StilKo'rinishi
.automaticStandart, tizim tanlaydi
.balancedSidebar va detail orasida muvozanat β€” ikkalasi ham joy egallaydi
.prominentDetailDetail ekran to'liq kenglikni egallaydi, menyu uning ustiga chiqadi

.prominentDetail ishlatilganda menyu detail ekranning chap tomonida emas, balki uning ustida (overlay) ko'rinadi β€” bu detail ekranni to'liq kenglikda ko'rsatish imkonini beradi.


Haqiqiy ma'lumotlar bilan misol

Endi NavigationSplitView-ni real ma'lumotlar bilan ishlatamiz β€” oziq-ovqat kategoriyalari va mevalar ro'yxati:

enum FoodCategory: String, CaseIterable {
    case fruits = "fruits"
    case vegetables = "vegetables"
    case meats = "meats"
}

enum Fruit: String, CaseIterable {
    case apple = "apple"
    case banana = "banana"
    case orange = "orange"
}

struct NavigationSplitViewBootcamp: View {

    @State private var visibility: NavigationSplitViewVisibility = .all
    @State private var selectedCategory: FoodCategory? = nil
    @State private var selectedFruit: Fruit? = nil

    var body: some View {
        NavigationSplitView(columnVisibility: $visibility) {
            // Sidebar β€” kategoriyalar ro'yxati
            List {
                ForEach(FoodCategory.allCases, id: \.self) { category in
                    Button(category.rawValue.capitalized) {
                        selectedCategory = category
                    }
                }
            }
            .navigationTitle("Kategoriyalar")
        } content: {
            // Content β€” tanlangan kategoriyaga mos elementlar
            if let selectedCategory {
                switch selectedCategory {
                case .fruits:
                    List {
                        ForEach(Fruit.allCases, id: \.self) { fruit in
                            Button(fruit.rawValue.capitalized) {
                                selectedFruit = fruit
                            }
                        }
                    }
                    .navigationTitle(selectedCategory.rawValue.capitalized)
                case .vegetables:
                    EmptyView()
                case .meats:
                    EmptyView()
                }
            } else {
                Text("Kategoriya tanlang")
            }
        } detail: {
            // Detail β€” tanlangan element haqida ma'lumot
            if let selectedFruit {
                Text("Siz tanladingiz: \(selectedFruit.rawValue.capitalized)")
                    .font(.largeTitle)
                    .navigationTitle(selectedFruit.rawValue.capitalized)
            } else {
                Text("Element tanlang")
            }
        }
    }
}

Ishlash tartibi: foydalanuvchi sidebar-dan kategoriya tanlaydi β†’ content ustunida o'sha kategoriyaga mos elementlar ro'yxati ko'rinadi β†’ element tanlanganda detail ustunida ma'lumot chiqadi.


Bo'sh holatlarni boshqarish

Hech narsa tanlanmagan paytda foydalanuvchiga bo'sh ekran ko'rsatish yomon tajriba hisoblanadi. Shuning uchun har bir ustunda fallback matn berish tavsiya etiladi:

} content: {
    if let selectedCategory {
        // ... kontent
    } else {
        Text("Boshlash uchun kategoriya tanlang")
    }
} detail: {
    if let selectedFruit {
        // ... kontent
    } else {
        Text("Ko'rish uchun biror narsa tanlang")
    }
}

iPhone-da ham ishlatish

NavigationSplitView standart holatda iPhone-da kutilganidek ishlamaydi β€” oddiy Button orqali tanlangan element keyingi ustunga o'tmaydi. Buning yechimi β€” List-ning selection parametridan foydalanish:

List(FoodCategory.allCases, id: \.self, selection: $selectedCategory) { category in
    Text(category.rawValue.capitalized)
}

Button o'rniga List-ning o'zini selection: $selectedCategory bilan to'g'ridan-to'g'ri bog'lash kerak. Shunda tanlash iPhone-da ham to'g'ri ishlaydi.

Oddiy Button o'rniga NavigationLink(value:) ishlatilganda, tanlangan element vizual ravishda ham ajratib ko'rsatiladi:

List(FoodCategory.allCases, id: \.self, selection: $selectedCategory) { category in
    NavigationLink(category.rawValue.capitalized, value: category)
}

NavigationLink bilan birga List-ning selection bog'lanishi β€” NavigationSplitView bilan ishlashning eng barqaror kombinatsiyasi.


Cheklovlar

  • Maksimal uchta ustun qo'llab-quvvatlanadi β€” to'rt yoki undan ko'p ustun kerak bo'lsa, o'z maxsus layout-ingizni yozish kerak bo'ladi
  • UI sozlamalari cheklangan β€” asosan List va navigationTitle bilan ishlashga mo'ljallangan, juda maxsus dizayn qiyinroq
  • iPhone-da ishlashi uchun qo'shimcha sozlash (List + selection) talab qilinadi

Xulosa

Bu videoda o'rgandik:

  • NavigationSplitView β€” bir vaqtda bir nechta ustunni ko'rsatuvchi navigatsiya komponenti, asosan iPad/Mac uchun
  • Ikki yoki uch ustunli versiyalar mavjud (sidebar+detail yoki sidebar+content+detail)
  • columnVisibility β€” .automatic, .doubleColumn, .detailOnly orqali boshlang'ich holatni belgilash
  • navigationSplitViewStyle β€” .balanced yoki .prominentDetail orqali joylashuv uslubini o'zgartirish
  • iPhone-da ishlashi uchun List-ning selection parametri va NavigationLink(value:) ishlatilishi kerak
  • Maksimal uch ustun, UI sozlamalari cheklangan
Buy mea coffee