Published on

SwiftUI-da ScrollView'dan qanday foydalanish kerak

Authors

Hammaga salom, xush kelibsiz! Men β€” Nik, va ushbu videoda biz ScrollViewlar haqida gaplashamiz. Bu nomidan ham ko'rinib turibdi β€” ScrollView, asosan, ekranga qo'shadigan, biz aylantirib (scroll) ko'rishimiz mumkin bo'lgan view, xolos. Ammo SwiftUI-da bu juda kuchli vosita: biz uni moslashtirishimiz mumkin, shunday qilib gorizontal yoki vertikal yo'nalishda aylantirib ko'rishimiz mumkin bo'ladi.

Va biz buni bir qadam oldinga olib boramiz: oldingi videoda o'rgangan ForEach bayonotini shu ScrollView ichiga joylashtirib, atigi bir necha qator kod bilan juda dinamik ekranlar yaratamiz. O'ylaymanki, bu juda ajoyib chiqadi β€” bilmadim, men ko'p qahva ichib qo'ydimmi, yoki ScrollView'lar haqiqatan ham shunchalik ajoyibmi, ammo keling, buni birga ko'rib chiqaylik.


Yangi loyiha fayli yaratish

Albatta, siz taxmin qilganingizdek, biz yana Xcode loyihamizdamiz. Har doimgidek, shu video uchun yangi fayl yaratamiz. Navigator'da o'ng tugmani bosib, yangi fayl yaratamiz β€” bu kursda har doim SwiftUI View bo'ladi. Bugun esa biz ScrollView'lar haqida gaplashayotganimiz uchun, buni ScrollViewBootcamp deb ataymiz. "Create" tugmasini bosamiz, hammasi ulangandan keyin esa canvas'da "Resume" tugmasini bosib, kod yozishni boshlaymiz.

Bu kursda men allaqachon VStack va HStacklarni, shuningdek ForEach tsikllarini ko'rib chiqgan edim β€” bular ushbu video uchun, asosan, zaruriy bilim hisoblanadi, va aynan shuning uchun men kursni shu tartibda olib bormoqdaman. Shuning uchun siz bu narsalardan qanday foydalanishni allaqachon bilasiz, deb taxmin qilib davom etaman.


Ekrandan tashqariga chiqib ketgan content muammosi

Avval ilovamizga VStack qo'shamiz, ichiga esa bitta Rectangle (to'rtburchak) qo'shib, unga balandligi 300 bo'lgan frame beramiz. Endi shu to'rtburchakni nusxalab, yana uch marta joylaymiz:

VStack {
    Rectangle()
        .frame(height: 300)
    Rectangle()
        .frame(height: 300)
    Rectangle()
        .frame(height: 300)
}

Ko'rib turganimizdek, bu to'rtburchaklar allaqachon ekrandan tashqariga chiqib ketmoqda. Xo'sh, bu view'ni qanday qilib aylantiriladigan (scrollable) qilamiz? Juda sodda: biz shu VStackni ScrollView ichiga joylaymiz.


ScrollView ichiga joylash β€” yechim

ScrollView deb yozib, qavslarni ochamiz, so'ngra mavjud VStackni qirqib olib, shu ScrollView ichiga joylaymiz:

ScrollView {
    VStack {
        Rectangle()
            .frame(height: 300)
        Rectangle()
            .frame(height: 300)
        Rectangle()
            .frame(height: 300)
    }
}

Ekranni aylantirib ko'rish uchun qilishingiz kerak bo'lgan yagona narsa β€” preview'ning yuqorisidagi Live Preview tugmasini bosish, shundan keyin bu kontent ustida tepaga-pastga aylantirib ko'rishingiz mumkin bo'ladi.

Agar shu qora to'rtburchaklarni rasm sifatida tasavvur qilsangiz, bu, aslida, Instagram lentasiga juda o'xshaydi β€” rasm va izoh, yana rasm va izoh, va siz buni tepaga-pastga aylantirib ko'rasiz. Demak, agar bizda juda ko'p to'rtburchak bo'lsa, biz aylantirishni davom ettirishimiz mumkin bo'ladi, deb tasavvur qilishingiz mumkin.


ForEach yordamida dinamik tsikl qo'shish

Endi to'rtburchakni qo'lda bir necha marta nusxalab joylashtirish o'rniga, keling, shu yerga ForEach tsiklini qo'shaylik. Avval pastdagi ikkita to'rtburchakni o'chirib, faqat bittasini qoldiramiz. ForEachni qo'shamiz, range variantidan foydalanamiz, va 0..<50 deb yozamiz. Tarkib (content) uchun Enter bosamiz, va har doimgidek standart parametr nomini indexga o'zgartiramiz. So'ngra shu to'rtburchakni shu ForEach ichiga joylaymiz, unga .fill(Color.blue) beramiz:

ScrollView {
    VStack {
        ForEach(0..<50) { index in
            Rectangle()
                .fill(Color.blue)
        }
    }
}

Endi preview'da pastga aylantirib ko'rsak, 50 ta to'rtburchak borligini, va biz ular ustida aylantirib ko'rishimiz mumkinligini ko'ramiz. Demak, shunchaki 0dan 50gacha sonlar o'rniga, haqiqiy ma'lumotlar to'plamimiz bo'lsa va biz shu ma'lumot ustida tsikl yuritsak, bu juda-juda foydali bo'lib qolishini tasavvur qilishingiz mumkin.


ScrollView'ni moslashtirish: indikatorni yashirish

Endi bir nechta narsani alohida ta'kidlab o'tmoqchiman. Aylantirib ko'rganimizda, o'ng tomonda kichik bir indikator borligini payqagan bo'lsangiz kerak. Agar xohlasak, bu indikatorni o'chirib qo'yishimiz mumkin.

ScrollView yaratganimizda, qavslarni ochsak, aslida ikki xil variant ko'ramiz: biri faqat content (tarkib) so'raydi, ikkinchisi esa axis (yo'nalish), showsIndicators (indikatorni ko'rsatish) va content'ni so'raydi. Biz ScrollView deb shunchaki qavs ochib yozganimizda, standart β€” faqat content variantidan foydalangan edik. Bu safar esa ikkinchi variantdan foydalanamiz: Enter bosamiz, yo'nalishni .vertical qilib qoldiramiz, showsIndicatorsni esa true qilib qoldiramiz. So'ngra avvalgi ScrollView'imizdagi VStackni qirqib olib, shu yangi ScrollView'ga joylaymiz, va eski ScrollView'imizni o'chirib tashlaymiz:

ScrollView(.vertical, showsIndicators: true) {
    VStack {
        ForEach(0..<50) { index in
            Rectangle()
                .fill(Color.blue)
        }
    }
}

Endi shu ScrollView initializer'ida qo'shimcha parametrlar bor: showsIndicators β€” bu, aslida, o'ng tomondagi kichik belgicha, xolos. Agar buni false qilsak, aylantirib ko'rishimiz mumkin bo'ladi, ammo qayerda turganimizni bildiruvchi hech qanday indikator bo'lmaydi:

ScrollView(.vertical, showsIndicators: false) {
    ...
}

Qisqa ro'yxatlarda ba'zi dasturchilar indikatorni ko'rsatishni xohlaydi, ammo, masalan, Instagram lentasi kabi holatlarda, ular bu indikatorning umuman ko'rinmasligini, go'yo bu cheksiz ekanligini xohlaydi β€” shuning uchun u yerda hech qanday indikator ko'rinmaydi.


Gorizontal yo'nalishda aylantirish

Albatta, taxmin qilganingizdek, biz yo'nalishni .verticaldan .horizontalga ham o'zgartirishimiz mumkin. Ammo agar gorizontal yo'nalishga o'tsak, ma'lumotlarimiz ham VStack o'rniga gorizontal stack, ya'ni HStack ichida bo'lishi kerak β€” aks holda ko'rinish g'alati bo'lib qoladi.

Shuning uchun yo'nalishni .horizontalga, VStackni esa HStackga o'zgartiramiz. Bu birozgina g'alati ko'rinadi, chunki to'rtburchaklarimizga kenglik (width) bermagan edik β€” agar shu to'rtburchaklarga kengligi 300, balandligi 300 bo'lgan frame bersak, endi shunday tarzda aylantirib ko'rishni boshlashimiz mumkin bo'ladi:

ScrollView(.horizontal, showsIndicators: false) {
    HStack {
        ForEach(0..<50) { index in
            Rectangle()
                .fill(Color.blue)
                .frame(width: 300, height: 300)
        }
    }
}

Real hayotiy misol: ScrollView ichida ScrollView

Davom etishdan oldin, sizlarga ScrollView'larni ScrollView'lar ichiga joylashtirib, juda chiroyli ekranlar yaratishning bir real hayotiy misolini ko'rsatib o'tmoqchiman. Keling, hozirgi kodimizni o'chirib, yangidan boshlaylik.

Avval oddiy ScrollView qo'shamiz, ichiga boshida qilganimizdek VStack joylaymiz, va VStack ichiga ForEach qo'shamiz β€” bu safar 0dan 10dan kichik qiymatgacha bo'lgan ma'lumot bilan. Tarkibda esa indexdan foydalanamiz, va burchak radiusi 25 bo'lgan RoundedRectangle (yumaloq burchakli to'rtburchak) qo'shamiz. Bu to'rtburchaklarga kengligi 200, balandligi 150 bo'lgan frame beramiz (tekislash shart emas), radiusi 10 bo'lgan soya (shadow) qo'shamiz. Soya har bir to'rtburchakning ustidan birozgina chiqib turgani uchun, soyadan keyin atrofiga biroz padding qo'shamiz β€” bu ko'rinishni biroz yaxshilaydi. Va nihoyat, shu to'rtburchaklarni oq rangga bo'yaymiz β€” .fill(Color.white):

ScrollView {
    VStack {
        ForEach(0..<10) { index in
            RoundedRectangle(cornerRadius: 25)
                .fill(Color.white)
                .frame(width: 200, height: 150)
                .shadow(radius: 10)
                .padding()
        }
    }
}

Endi bizda tepaga-pastga aylantirib ko'rishimiz mumkin bo'lgan, shablon vazifasini bajaruvchi to'rtburchaklar qatori bor.


Har bir qatorga ham gorizontal ScrollView qo'shish

Keling, buni yanada bir qadam oldinga olib boraylik. Shu ForEach ichida, ya'ni har bir qatorda, yana bir ScrollView qo'shamiz β€” bu safar boshqa variantdan foydalanib, uni .horizontal qilib o'zgartiramiz, showsIndicatorsni esa false qilib qo'yamiz. Tarkib uchun esa, chap-o'ngga harakatlanamiz deganimiz uchun, HStack qo'shamiz, va o'sha yumaloq burchakli to'rtburchakni shu HStack ichiga joylaymiz:

ScrollView {
    VStack {
        ForEach(0..<10) { index in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack {
                    RoundedRectangle(cornerRadius: 25)
                        .fill(Color.white)
                        .frame(width: 200, height: 150)
                        .shadow(radius: 10)
                        .padding()
                }
            }
        }
    }
}

Demak, endi bizda ichida VStack bo'lgan vertikal ScrollView bor, va ForEach(0..<10) tufayli unda 10 ta qator bor β€” shu 10 qator ustida tepaga-pastga aylantirib ko'rishimiz mumkin. Va har bir qatorda esa yana bir, bu safar gorizontal ScrollView bor, ichida esa bitta yumaloq to'rtburchak joylashgan HStack bor β€” shuning uchun har bir qatorni alohida chap-o'ngga aylantirib ko'rishimiz mumkin, garchi hozircha unda faqat bitta to'rtburchak bo'lsa ham.


Har bir qatorni ham ForEach bilan to'ldirish

Keling, shu view'ni yakunlaylik β€” har bir qatorga yana bir ForEach tsikli qo'shamiz. Shu HStack ichida ForEach qo'shamiz, ma'lumot sifatida 0dan 20dan kichik qiymatgacha bo'lgan oraliqni beramiz. Yana Enter bosamiz, parametrni index deb qo'yamiz, va o'sha yumaloq to'rtburchakni shu ichki ForEach ichiga joylaymiz:

ScrollView {
    VStack {
        ForEach(0..<10) { index in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack {
                    ForEach(0..<20) { index in
                        RoundedRectangle(cornerRadius: 25)
                            .fill(Color.white)
                            .frame(width: 200, height: 150)
                            .shadow(radius: 10)
                            .padding()
                    }
                }
            }
        }
    }
}

Bilaman, ba'zilaringiz uchun bu kod birozgina chalkash bo'lib qolayotgan bo'lishi mumkin, ammo bu yerda nima sodir bo'layotganini tushunib olganingizdan so'ng, shunchalik ajoyib ekranni qanchalik oson yaratish mumkinligini ko'rasiz. Endi biz chap-o'ngga ham, tepaga-pastga ham aylantirib ko'rishimiz mumkin β€” bu, aynan, Spotify yoki Netflix kabi ko'plab ilovalarda ishlatiladigan shablon. Shunchaki 0dan 10gacha va 0dan 20gacha bo'lgan sonlar ustida tsikl yuritish o'rniga, siz haqiqiy ma'lumotlar to'plamlari ustida tsikl yuritib, har bir qo'shiqingizni, har bir filmingizni shu yerlarga joylashtirishingiz mumkin β€” shunda har birining o'z rasmi, o'z rangi, o'z sarlavhasi bo'ladi, va siz atigi bir necha qator kod bilan juda ajoyib bir ekranga ega bo'lasiz.


LazyVStack va LazyHStack β€” samaradorlikni oshirish

Videoni tugatishdan oldin, yana bir narsani aytib o'tmoqchiman. Oddiy VStack yoki HStackda, shu stack ichidagi barcha kontent ekran yaratilishi bilanoq darhol yuklanadi. Bu, odatda, kichik ma'lumotlar to'plamlari uchun muammo emas.

Ammo agar shu VStackda, masalan, ForEachni o'zgartirib, 100 ta qator bo'lganda nima bo'ladi? Ekran yuklanganda biz, ehtimol, faqat birinchi, ikkinchi, uchinchi, to'rtinchi qatorni, va besh inchi qatorning ozgina qismini ko'ramiz β€” barcha 100 qatorni ko'rmaymiz. Demak, bizga ekran paydo bo'lishi bilanoq barcha 100 qatorning yuklanishi shart emas β€” chunki, masalan, har bir katakchada rasm yuklab olayotganimizni tasavvur qiling: har safar shu katak ekranga chiqganda, o'sha film yoki qo'shiq uchun rasmni yuklab olishimiz kerak bo'ladi. Bu esa, hozircha bizga faqat ekrandagi narsa kerak bo'lsa ham, juda ko'p ma'lumotni yuklab olishga olib keladi.

SwiftUI-da buni tuzatishning juda qulay usuli bor: VStack chaqirish o'rniga, biz shunchaki LazyVStack chaqirishimiz mumkin. Bu, aslida, shunchalik oddiy β€” VStack yoki HStackdan oldin lazy so'zini qo'shish, xolos:

ScrollView {
    LazyVStack {
        ForEach(0..<100) { index in
            // qator (row)
        }
    }
}

Buni "lazy" (erinchak/kechiktiriladigan) qilib qo'yish, asosan, shu qator yoki elementni faqat kerak bo'lganda yaratadi, degani. Demak, bizda 100 qator bo'lganda va bu LazyVStack ichida bo'lganda, biz faqat dastlabki bir nechta qatorni yaratamiz, va ilovaning "sahna ortida", aylantirib borishimiz davomida, qolgan qatorlar asta-sekin yaratiladi. Shunday qilib, ilovamizni yuklab, 100 qatorni bir vaqtning o'zida yaratish o'rniga, biz buni "lazy" qilib qo'yamiz β€” bu esa ilovamizni ancha samaraliroq qiladi, hamda keraksiz ma'lumotni yuklab olishning oldini oladi. Axir, agar foydalanuvchi shu ekranni ochib, hech qachon pastgacha aylantirib ko'rmasa-chi? Bu holda bizga umuman shu ma'lumotni yuklab olish kerak ham bo'lmagan bo'lardi.

Shuning uchun, katta ma'lumotlar to'plamlari bilan ishlaganingizda, imkon qadar lazy stacklardan foydalanishni tavsiya qilaman. HStack uchun ham xuddi shunday β€” uni LazyHStack qilib qo'yishimiz mumkin. Va ko'pincha, bu "lazy" ekanligini siz sezmaysiz ham, chunki "sahna ortida" u bu elementlarni aynan qachon yaratish kerakligini biladi β€” ular ekranga chiqishidan sal oldin yaratiladi, xolos.


Demak, ushbu video uchun shu, xolos β€” bu ScrollView'larga qisqacha kirish edi, shu bilan birga biz lazy stacklarga ham birozgina to'xtalib o'tdik. Endi siz katta ma'lumotlar to'plamlari bilan qanday ishlashni, va view'laringizni vertikal hamda gorizontal yo'nalishda qanday aylantiriladigan qilishni bilasiz.

Umid qilamanki, ushbu video sizlarga yoqdi. Agar yoqgan bo'lsa, albatta obuna bo'lish tugmasini bosing, va agar biror narsa o'rgangan bo'lsangiz, hamda meni xursand qilishni xohlasangiz β€” layk tugmasini ham bosib qo'ying. Har doimgidek, men β€” Nik, bu Swiftful Thinking, keyingi videoda ko'rishamiz!

Buy mea coffee