- Published on
SwiftUI-da Mask yordamida 5 yulduzli reyting tugmasi yaratish
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Mask modifikatori kamdan-kam ishlatiladigan, ammo juda qiziqarli va kuchli vosita. Biz ushbu videoda klassik 5 yulduzli reyting komponentini yasaymiz β ko'plab ilovalarda ko'rgan narsamizni. Mask qanday ishlaydi: pastki qatlam (yulduzlar) mavjud, ustiga rectangle qo'yamiz, va shu rectangle'ni pastki qatlamning shakliga moslashtirish uchun mask ishlatamiz β natijada rectangle faqat yulduzlar shaklidagi joyni ko'rsatadi.
1-qadam: Oddiy yulduzli reyting (masksiz)
Avval masksiz, oddiy usulda yaratib ko'ramiz:
@State var rating: Int = 3
var body: some View {
HStack {
ForEach(1..<6) { index in
Image(systemName: "star.fill")
.font(.largeTitle)
.foregroundColor(rating >= index ? Color.yellow : Color.gray)
.onTapGesture {
rating = index
}
}
}
}
rating >= index β reytingdan kichik yoki teng bo'lgan barcha yulduzlarni sariq qiladi. Simulyatorda bosib ko'rsak, yulduzlar o'zgaradi, ammo sakrab o'zgaradi β animatsiya yo'q. Ko'plab ilova uchun bu yetarli, ammo biz mask yordamida buni ancha chiroyliroq qila olamiz.
2-qadam: starsView komponentini ajratish
HStackni alohida private varga chiqaramiz, va foreground rangini doim kulrang qilib qo'yamiz β keyinchalik rangni mask orqali boshqaramiz:
private var starsView: some View {
HStack {
ForEach(1..<6) { index in
Image(systemName: "star.fill")
.font(.largeTitle)
.foregroundColor(Color.gray)
.onTapGesture {
withAnimation(.easeInOut) {
rating = index
}
}
}
}
}
bodyda esa:
var body: some View {
ZStack {
starsView
.overlay(overlayView.mask(starsView))
}
}
3-qadam: overlayView β reyting kengligidagi rectangle
overlayView β bu yulduzlar ustiga qo'yiladigan sariq rectangle. Uning kengligi reytingga qarab o'zgaradi. Aniq kenglikni olish uchun GeometryReader kerak:
private var overlayView: some View {
GeometryReader { geometry in
ZStack(alignment: .leading) {
Rectangle()
.foregroundColor(Color.yellow)
.frame(width: CGFloat(rating) / 5 * geometry.size.width)
}
}
.allowsHitTesting(false)
}
Mantiq:
CGFloat(rating) / 5β reytingning nisbati (masalan, 3/5 = 0.6)* geometry.size.widthβ to'liq kenglikning shu nisbatdagi qismiZStack(alignment: .leading)β rectangle chap tomondan boshlanadi.allowsHitTesting(false)β overlay qatlamiga bosish o'tib, pastdagi yulduzlarga boradi (quyida tushuntirish)
4-qadam: Mask qo'llash
var body: some View {
ZStack {
starsView
.overlay(
overlayView
.mask(starsView)
)
}
}
Nima sodir bo'ladi:
starsViewβ kulrang yulduzlar (pastki qatlam)overlayViewβ sariq rectangle (ustki qatlam), kengligi reytingga qarab o'zgaradi.mask(starsView)β sariq rectangle'ni yulduzlar shakliga moslashtiradi
Natijada: sariq rang faqat yulduz shaklida ko'rinadi, va kenglik reytingga qarab chap tomondan to'ldiriladi.
allowsHitTesting nima uchun kerak
.overlay qo'shilganda, ustki qatlam (overlayView) pastki qatlamning ustini yopadi β onTapGesturelar endi ishlamay qoladi, chunki foydalanuvchi overlay'ni bosadi, yulduzlarni emas. .allowsHitTesting(false) esa overlay'ni "shaffof" qiladi β bosishlar u orqali o'tib, pastdagi starsViewga boradi.
To'liq kod
struct MaskBootcamp: View {
@State var rating: Int = 3
var body: some View {
ZStack {
starsView
.overlay(
overlayView
.mask(starsView)
)
}
}
private var starsView: some View {
HStack {
ForEach(1..<6) { index in
Image(systemName: "star.fill")
.font(.largeTitle)
.foregroundColor(Color.gray)
.onTapGesture {
withAnimation(.easeInOut) {
rating = index
}
}
}
}
}
private var overlayView: some View {
GeometryReader { geometry in
ZStack(alignment: .leading) {
Rectangle()
.foregroundColor(Color.yellow)
.frame(width: CGFloat(rating) / 5 * geometry.size.width)
}
}
.allowsHitTesting(false)
}
}
Live Preview'da sinab ko'rsak: yulduzni bosganimizda, sariq rang chap tomondan silliq animatsiya bilan to'ldiriladi yoki qisqaradi β bu juda professional ko'rinadi.
Bonus: Gradient qo'shish
Rectangle'ni sariq rangda qoldirish shart emas β unga gradient ham qo'shishimiz mumkin:
Rectangle()
.fill(
LinearGradient(
gradient: Gradient(colors: [.red, .blue]),
startPoint: .leading,
endPoint: .trailing
)
)
.frame(width: CGFloat(rating) / 5 * geometry.size.width)
Yulduzlar endi chapdan qizil, o'ngdan ko'k rangda to'ladi β atigi bir necha qator kod o'zgartirish bilan ajoyib effekt.
Xulosa
Mask ishlash mantig'i:
- Pastki qatlam β asl view (yulduzlar)
- Ustki qatlam β moslashtiriladigan view (rectangle)
.mask(pastki_qatlam)β ustki qatlamni pastki qatlamning shakliga kesadi
Kenglik o'zgartirilganda mask ham mos ravishda o'zgaradi β natijada chiroyli, animatsiyalangan reyting komponenti yaratiladi.