- Published on
SwiftUI-da qayta ishlatiladigan ActionSheet qanday yasash kerak
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Yana xush kelibsiz! Men — Nik, va ushbu videoda biz action sheetlar haqida gaplashamiz. Agar oldingi, alert'lar haqidagi videoni tomosha qilgan bo'lsangiz, bu video sizga juda tanish tuyulishi mumkin — chunki action sheet'lar va alert'lar, asosan, bir xil narsa, faqat alert ekranning markazida, action sheet esa ekranning pastida paydo bo'ladi. Bu yerdagi asosiy farq shunda: action sheet'ga biz juda ko'p tugma qo'shishimiz mumkin, alert esa faqat ikki tugma bilan cheklangan edi. Shuning uchun, agar foydalanuvchiga biror narsa taqdim etishni xohlasangiz, va ularda ikkidan ko'proq, masalan to'rt yoki besh xil tanlov bo'lishini xohlasangiz — action sheet aynan shunday holatlar uchun juda yaxshi UI hisoblanadi.
Men ko'plab professional ilovalar aynan shu vositadan foydalanganini ko'rgan — masalan, Instagram'da post burchagidagi uchta nuqtani (...) bossangiz, pastdan aynan shunday action sheet chiqadi. Mana shu — biz ushbu videoda o'rganadigan narsa.
Yangi loyiha fayli yaratish
Yana Xcode loyihamizga qaytdik — shu video uchun yangi fayl yaratamiz: Navigator'da o'ng tugmani bosib, yangi fayl yaratamiz, bu SwiftUI View bo'ladi, va biz action sheet'lar haqida gaplashayotganimiz uchun buni ActionSheetBootcamp deb ataymiz. "Create" tugmasini bosamiz, ichkariga kirgach esa canvas'da "Resume" tugmasini bosib, kod yozishni boshlaymiz.
Oldingi videoda aytib o'tganimdek, action sheet'lar alert'larga juda o'xshash — shuning uchun agar oldingi videoni kuzatib borgan bo'lsangiz, bu videoni ham juda oson tushunib olishingiz kerak.
Oddiy ActionSheet ko'rsatish
Avval view'imizga bir tugma qo'shamiz — sarlavhasi "Click me" bo'lsin, harakat uchun esa Enter bosib, hozircha bo'sh qoldiramiz. Shu tugmadan keyin, action sheet uchun modifikator qo'shamiz: .actionSheet deb yozamiz, va isPresented bilan contentga ega bo'lgan variantdan foydalanamiz. Albatta, isPresented o'ziga bog'langan Boolean talab qiladi — bu, xuddi .sheet, .fullScreenCover va .alertda bo'lgani kabi, xolos, shuning uchun bu sizga endi tanish bo'lishi kerak.
Yuqorida @State var showActionSheet, turi Bool, qiymati false bo'lgan o'zgaruvchi yaratamiz (bu o'zgaruvchilarga, albatta, xohlagan nomingizni berishingiz mumkin — men ularni odatda nima qilishiga mos nom berishni yoqtiraman, shuning uchun showActionSheet juda tushunarli). Buni dollar belgisi bilan bog'laymiz: $showActionSheet. Endi bizga tarkib (content) qaytarishimiz kerak — agar Option tugmasini bosib ActionSheetning ustiga bossak, bu tarkib aslida ActionSheet qaytarishi kerakligini ko'ramiz.
Shuning uchun shu yerga ActionSheet deb yozamiz, qavslarni ochsak, ikki xil variant ko'ramiz: faqat sarlavhaga ega standart variant, va message hamda tugmalar massivi (array)ga ega bo'lgan variant. Avval sarlavhali variantdan boshlaymiz, chunki bu sodda — Enter bosamiz, va Text qo'shamiz: "This is the title".
Tugmani bosganimizda action sheet ko'rinishini xohlaymiz, shuning uchun tugma harakati ichida showActionSheet.toggle()ni chaqiramiz:
@State var showActionSheet: Bool = false
var body: some View {
Button("Click me") {
showActionSheet.toggle()
}
.actionSheet(isPresented: $showActionSheet) {
ActionSheet(title: Text("This is the title"))
}
}
Canvas'da "Resume" tugmasini bosib, Live Preview'ni ishga tushiramiz, va tugmamizni bossak, action sheet pastdan chiqib kelishini ko'ramiz. Demak, action sheet — bu xuddi alert kabi narsa, faqat alert ekranning markazida, action sheet esa pastdan chiqadi. Hozircha bu biroz noqulay ko'rinadi, chunki faqat sarlavha variantidan foydalandik, ammo hozir ishlatadigan boshqa variant orqali bu yerga ko'plab tugma qo'shishimiz mumkin bo'ladi.
Funksiyani body'dan tashqariga chiqarish
Ammo barcha qo'shimcha tugmalarni qo'shishdan oldin, keling, shu kodni biroz tozalab olaylik. Agar ushbu kursni kuzatib borgan bo'lsangiz, bilasizki, men mantiqni view'dan iloji boricha ko'proq ajratib chiqarishni yoqtiraman — bu, ayniqsa, oldingi videoda ko'rgan alert'lar va shu action sheet'lar uchun juda yaxshi amaliyot, chunki bu butun mantiqni bodydan tashqariga chiqarib, body kodini biroz tozalaydi.
bodydan tashqarida, pastda, getActionSheet nomli funksiya yaratamiz, qavslarini ochib-yopamiz, bu funksiya ActionSheet qaytarishi kerak. Ichiga return yozib, avvalgi ActionSheetimizni qirqib olib shu yerga joylaymiz, so'ngra body'dagi tarkib o'rniga shunchaki getActionSheet()ni chaqiramiz (aslida buni alert videosida ham qilishim kerak edi, ammo hech bo'lmasa hozir ko'rib turibsiz):
func getActionSheet() -> ActionSheet {
return ActionSheet(title: Text("This is the title"))
}
var body: some View {
Button("Click me") {
showActionSheet.toggle()
}
.actionSheet(isPresented: $showActionSheet) {
getActionSheet()
}
}
Ko'rib turganingizdek, bu yana juda toza va tartibli, va barcha mantiqimiz pastda joylashgan. Canvas'da "Resume" tugmasini bossak, hamon ishlayveradi — tugmani bossak, action sheet ko'rinaveradi.
Title, message va bir nechta tugma
Endi keling, ancha murakkabroq action sheet qo'shaylik. Avvalgisini izohga olib, pastida yana bir ActionSheet qaytaramiz — bu safar title, message va buttons variantidan foydalanamiz. O'qilishi osonroq bo'lishi uchun, sarlavha, xabar va tugmalarni har birini o'z qatoriga joylashtiraman.
Avval sarlavha kerak — shunchaki Text("This is the title") deb yozamiz. Keyin xabar kerak — bu optional, shuning uchun nil qoldirib qo'yishimiz ham mumkin, ammo biz ozgina tasvir qo'shamiz: Text("This is the message").
So'ngra bizga ActionSheet.Button turidagi tugmalar massivi kerak bo'ladi. Bu massivni to'g'ridan-to'g'ri shu yerda ham yaratishingiz mumkin, ammo men bu tugmalarni alohida, shu chaqiruvdan tashqarida yaratishni osonroq deb hisoblayman. Shuning uchun, returndan oldin, o'z tugmalarimni yarataman:
let button1, turi ActionSheet.Button, va nuqta qo'yib qarasak — bu yerda aynan oldingi videoda alert'da ko'rgan bilan bir xil tugma variantlarini ko'ramiz: ko'k rangdagi cancel tugmalari, ko'k rangdagi default tugmalar, va qizil rangdagi destructive tugmalar. Keling, har birining bittadan namunasini qo'shamiz: avval label'ga ega default tugma — matni "Default" bo'lsin. Keyin let button2, turi xuddi shunday, label'ga ega destructive tugma — matni "Destructive" (bu yerga ham, agar xohlasak, harakat qo'shishimiz mumkin, ammo hozircha shunchaki label bilan qoldiramiz). Va nihoyat, let button3 — cancel tugmasi:
func getActionSheet() -> ActionSheet {
let button1: ActionSheet.Button = .default(Text("Default"))
let button2: ActionSheet.Button = .destructive(Text("Destructive"))
let button3: ActionSheet.Button = .cancel()
return ActionSheet(
title: Text("This is the title"),
message: Text("This is the message"),
buttons: [button1, button2, button3]
)
}
Tugmalar massivimizga esa shunchaki button1, button2, button3ni qo'yamiz (albatta, bu mantiqning hammasini to'g'ridan-to'g'ri massiv ichiga yozish ham mumkin edi, ammo bu usul ancha toza va tartibli, deb o'ylayman).
Endi sinab ko'raylik: "Click me"ni bossak, sarlavha va xabarga ega action sheet'ni, shuningdek ikki turli tugma va bitta cancel tugmasini ko'ramiz. Bu yerga yanada ko'proq tugma ham qo'shishimiz mumkin — masalan, button1ni nusxalab, bir necha marta qo'shsam, action sheet'da bir nechta default tugma, bitta destructive tugma va cancel tugmasi paydo bo'ladi.
Demak, oxir-oqibatda, action sheet'lar oldingi videoda o'rgangan alert'lar bilan deyarli bir xil — faqat action sheet'larga juda ko'p tugma qo'shishimiz mumkin, alert'larda esa biz faqat ikki tugma bilan cheklanganmiz. Alert markazda chiroyli pop-up sifatida chiqadi, action sheet esa pastdan chiqadi — ikkalasi ham ilovalarda doimiy ishlatiladi.
Real hayotiy misol: Instagram shablon
Davom etishdan oldin, sizlarga bu action sheet'lar qayerda ishlatilishi mumkinligi va uni qanday qilib biroz dinamik qilish mumkinligi haqida real hayotiy misol ko'rsatib o'tmoqchiman. Keling, hozirgi tugmamizni o'chirib, view'imizni tahrirlashdan boshlaylik.
Avval HStack qo'shamiz: chap tomonida — kengligi va balandligi 30 bo'lgan Circle (tekislash kerak emas), uning yonida — "@username" matni, so'ngra Spacer, va o'ng tomonida esa tizim belgisi "ellipsis" (uchta nuqta) bo'lgan Image. Canvas'da "Resume" tugmasini bosib ko'rinishini ko'raylik — qayoqqa olib borayotganimni payqagan bo'lsangiz kerak.
Endi shu HStackni VStack ichiga joylaymiz, va action sheet modifikatorini ham shu VStackga ko'chiramiz (bu shart emas, men buni shunchaki yo'lda turmasligi uchun qilyapman). HStackning pastiga esa, kvadrat shaklidagi Rectangle qo'shamiz — bu uchun aspectRatiodan foydalanamiz, qiymat sifatida 1.0, kontent rejimi esa .fit bo'ladi. HStackga gorizontal padding ham qo'shamiz:
VStack {
HStack {
Circle()
.frame(width: 30, height: 30)
Text("@username")
Spacer()
Image(systemName: "ellipsis")
}
.padding(.horizontal)
Rectangle()
.aspectRatio(1.0, contentMode: .fit)
}
.actionSheet(isPresented: $showActionSheet) {
getActionSheet()
}
Ko'rib turganingizdek, endi bizda view'da Instagram shabloniga juda o'xshash narsa bor — va buni qilish juda oson bo'ldi. Endi shu uchta nuqtali rasmni tugmaga aylantiraylik: shu Imagening o'rniga Button qo'shamiz, action va labelga ega bo'lgan variantdan foydalanamiz. Harakat sifatida showActionSheet.toggle()ni chaqiramiz, label uchun esa shu Imageni qirqib olib, shu yerga joylaymiz. Bu, albatta, standart bo'yicha ko'k rangda ko'rinadi, shuning uchun rangini o'zgartiramiz: .accentColor(.primary) — bu uni qora rangga aylantiradi:
Button(action: {
showActionSheet.toggle()
}, label: {
Image(systemName: "ellipsis")
})
.accentColor(.primary)
Endi ekranimizda Instagram shablonimiz bor, va uchta nuqtani bosib, action sheet'ni ko'rishimiz mumkin.
ActionSheet'ni dinamik qilish: enum yordamida
Keling, shu uchta nuqtani dinamik qilaylik — shunday qilib, kim o'z postini, kim esa boshqa birovning postini bossa, tugmalar shunga mos o'zgaradi. Buni boshqarish uchun ikki holatga ega bo'lamiz, va buni enum yordamida amalga oshiramiz.
Yuqorida enum ActionSheetOptions yaratamiz, qavslarni ochamiz, va ikki case qo'shamiz: case isMyPost va case isOtherPost (bu nomlash, ehtimol, eng yaxshisi emas, ammo hozircha shu bilan davom etamiz). Endi qaysi holat hozir amal qilayotganini boshqaradigan o'zgaruvchi yaratamiz: @State var actionSheetOption, turi — ActionSheetOptions, va boshlang'ich qiymat sifatida .isOtherPostni qo'yamiz, ya'ni boshida "bu boshqa birovning posti" deb hisoblaymiz:
enum ActionSheetOptions {
case isMyPost
case isOtherPost
}
@State var actionSheetOption: ActionSheetOptions = .isOtherPost
Endi shu tugmani bosganimizda, biz actionSheetOptionni xohlagan holatga — "bu mening postim" yoki "bu boshqa birovning posti"ga — o'rnatishimiz mumkin. Hozircha shunchaki uni .isOtherPostga o'rnatamiz, ya'ni boshqa birovning posti bo'lgan holatdan boshlaymiz:
Button(action: {
actionSheetOption = .isOtherPost
showActionSheet.toggle()
}, label: {
Image(systemName: "ellipsis")
})
.accentColor(.primary)
Endi getActionSheet funksiyamizda tugmalarimizni yangilaymiz. Avvalgi mantiqni izohga olib (shunday qilib u hamon turadi), va toza joydan boshlaymiz. Avval kerakli barcha tugmalarni yarataylik:
let shareButton, turi ActionSheet.Button, qiymati — actionga ega default (ko'k rangli bo'lsin xohlaymiz), matni "Share" — harakat ichida hozircha hech narsa yo'q, ammo aynan shu yerga postni ulashish kodi yoziladi.
let reportButton — actionga ega destructive, matni "Report" — bu yerga ham hozircha bo'sh qoldiramiz, ammo aynan shu yerga postni shikoyat qilish kodi yoziladi.
let deleteButton — yana actionga ega destructive, matni "Delete" — bu yerga ham postni o'chirish kodi yoziladi.
Va nihoyat, let cancelButton — oddiy cancel tugmasi.
Endi shu ikki holatni boshqarishimiz kerak: action sheet ko'rsatilganda, bu albatta "mening postim" yoki "boshqa birovning posti" bo'ladi. Shuning uchun actionSheetOption ustida switch qilamiz. Agar bu boshqa birovning posti bo'lsa (case .isOtherPost), title, message va buttonsga ega action sheet qaytaramiz — sarlavha "What would you like to do?" bo'ladi, xabar kerak emas, shuning uchun nil qoldiramiz, tugmalar massivida esa shareButton, reportButton va cancelButtonni qo'shamiz — deleteButtonni esa qasddan qo'shmaymiz, chunki postni faqat u mening postim bo'lsagina o'chirish imkoni bo'lishi kerak, boshqa birovning postini esa o'chirish imkoni bo'lmasligi kerak.
Ikkinchi holat uchun (case .isMyPost) esa, sarlavha aynan bir xil bo'lishi kerak, shuning uchun buni alohida o'zgaruvchiga chiqarib, ikkala holatda ham shu o'zgaruvchiga murojaat qilamiz: let title, qiymati — Text("What would you like to do?"). Bu safar esa tugmalar massiviga deleteButtonni ham qo'shamiz:
func getActionSheet() -> ActionSheet {
let title = Text("What would you like to do?")
let shareButton: ActionSheet.Button = .default(Text("Share"), action: {
// postni ulashish kodi shu yerga yoziladi
})
let reportButton: ActionSheet.Button = .destructive(Text("Report"), action: {
// postni shikoyat qilish kodi shu yerga yoziladi
})
let deleteButton: ActionSheet.Button = .destructive(Text("Delete"), action: {
// postni o'chirish kodi shu yerga yoziladi
})
let cancelButton: ActionSheet.Button = .cancel()
switch actionSheetOption {
case .isOtherPost:
return ActionSheet(
title: title,
message: nil,
buttons: [shareButton, reportButton, cancelButton]
)
case .isMyPost:
return ActionSheet(
title: title,
message: nil,
buttons: [shareButton, reportButton, deleteButton, cancelButton]
)
}
}
Bu yerda biz default holatini qo'shishimiz shart emas, chunki barcha holatlarni — bor-yo'g'i ikkitasini ham — to'liq qamrab oldik, va bu o'zgaruvchi har doim aynan shu ikki qiymatdan biri bo'ladi.
Keling, buni sinab ko'raylik: hozircha tugma actionSheetOptionni .isOtherPostga o'rnatadi, ya'ni bu boshqa birovning posti. Uchta nuqtani bossak: "What would you like to do?", "Share", "Report", "Cancel". Endi agar shu qiymatni .isMyPostga o'zgartirsak (haqiqiy ilovada, albatta, sizda bu mening postim yoki yo'qligini aniqlash uchun o'z mantig'ingiz bo'ladi), uchta nuqtani bosganimizda xuddi shu action sheet'ni ko'ramiz, ammo bu safar unda "Delete" funksiyasi ham bor — chunki bu safar bu mening postim.
Xulosa
Mana shu — ushbu video uchun shu, xolos. Action sheet'lar ham juda foydali: foydalanuvchiga bir nechta turli tanlovni taqdim etishingiz kerak bo'lgan har qanday holatda, action sheet — bu juda-juda oson yo'l. Sarlavha va xabar nima deyishini moslashtirishingiz mumkin, tugmalarni ko'k yoki qizil qilishingiz mumkin, va, albatta, ularga juda ko'p tugma ham qo'shishingiz mumkin — masalan, shu kabi vaziyatda besh yoki o'n xil tugma qo'shishimiz ham mumkin edi.
Umid qilamanki, ushbu video sizlarga yoqdi — agar ba'zi videolarda o'zimni qaytarayotganimni payqasangiz, uzr so'rayman, ammo action sheet haqiqatan ham alert'ga, shuningdek .sheet modifikatoriga juda o'xshaydi. Ammo oxir-oqibat, bularning barchasi ilovangizni yaratishda juda muhim narsalar, va ularning qanday ishlashini, qanday amalga oshirilishini, qanday dinamik qilinishini tushunib olish, kelajakda sizga juda ko'p vaqtni tejab beradi.
Yana bir bor, umid qilamanki, sizlar biror narsa o'rgandingiz. Har doimgidek, men — Nik, bu Swiftful Thinking, keyingi videoda ko'rishamiz!