- Published on
Spotify kloni (2-qism): Grid va Yangi Relizlar komponentlari
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Asosiy oyna ustida ishlashda davom etamiz
Oldingi darsda biz yuqori qismdagi menyu qatorini yig'ib chiqdik. Endi Spotify tarmog'iga xos bo'lgan "Yaqinda eshitilganlar" (Recent section) hamda bitta kattaroq chiqib turuvchi "Yangi reliz" (New release) qismlarini yaratamiz.
1. Yaqinda eshitilganlar (Recent Section)
Bu qism odatda 6 yoki 8 ta kichik to'rtburchak katakchalardan (cells) tashkil topgan bo'lib, ikkita ustunli (column) ko'rinishda joylashadi.
Avvalo kichik katakchani SpotifyRecentCell nomi bilan alohida yaratib olamiz:
import SwiftUI
struct SpotifyRecentCell: View {
var imageName: String = "https://picsum.photos/600/600"
var title: String = "Some random title"
var body: some View {
HStack(spacing: 16) {
ImageLoaderView(urlString: imageName)
.frame(width: 55, height: 55)
Text(title)
.font(.callout)
.fontWeight(.semibold)
.lineLimit(2) // Maksimum 2 qator
Spacer()
}
.padding(.trailing, 8)
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color.spotifyDarkGray)
.cornerRadius(6)
}
}
Bu katakchalarni ikkita ustunga chiroyli qilib joylashtirish uchun SwiftUI dagi odatiy LazyVGrid dan emas, balki oldingi safar biz o'rnatgan paketimiz — SwiftfulUI dagi NonLazyVGrid dan foydalanamiz. Kichik ro'yxatlarda u ancha chiroyliroq va xatosiz ishlaydi:
NonLazyVGrid(columns: 2, alignment: .center, spacing: 10, items: products) { product in
if let product {
SpotifyRecentCell(
imageName: product.images.first ?? "",
title: product.title
)
}
}
2. Takrorlanuvchi dizayn uchun ViewModifier
Bizning "Yaqinda eshitilganlar" katakchasimizning fon rangi va tekstining rangi (kulrang fon, oq tekst) xuddi yuqoridagi Kategoriyalar menyusi kabi bir xil. Ikkala joyga ham bir xil uzunlikdagi rang kodlarini yozib yotmaslik uchun, ViewModifier orqali themeColors degan yordamchi funksiya yaratib olamiz:
extension View {
func themeColors(isSelected: Bool) -> some View {
self
.background(isSelected ? Color.spotifyGreen : Color.spotifyDarkGray)
.foregroundColor(isSelected ? Color.spotifyBlack : Color.spotifyWhite)
}
}
Endi shunchaki .themeColors(isSelected: false) deb chaqirsak, qolgan hamma rang kodlari avtomatik tushadi.
3. "Yangi Reliz" (New Release) komponenti
Bu huddi bitta katta yangilik kabi ko'rinadigan qism. Unda artist rasmi, albom cover'i (rasmi) va ikkita tugma bor.
Biz qismlarni qanchalik ko'p "Component" larga bo'lib tashlasak (modullashtirsak), asosiy kodimiz (Home View) shunchalik toza va ixcham bo'ladi:
struct SpotifyNewReleaseCell: View {
var imageName: String
var headline: String?
var subheadline: String?
var title: String?
var subtitle: String?
// Tugmalar uchun maxsus opsional harakatlar (closures)
var onAddToPlaylistPressed: (() -> Void)? = nil
var onPlayPressed: (() -> Void)? = nil
var body: some View {
VStack(spacing: 16) {
// ... (Tepada Artist rasmi va ismi bo'lgan HStack)
HStack {
ImageLoaderView(urlString: imageName)
.frame(width: 140, height: 140)
VStack(alignment: .leading, spacing: 32) {
VStack(alignment: .leading, spacing: 2) {
Text(title ?? "")
.font(.callout)
.fontWeight(.semibold)
.foregroundColor(.spotifyWhite)
Text(subtitle ?? "")
.font(.callout)
.foregroundColor(.spotifyLightGray)
}
HStack(spacing: 0) {
Image(systemName: "plus.circle")
.foregroundColor(.spotifyLightGray)
.font(.title3)
.padding(4)
.onTapGesture {
onAddToPlaylistPressed?() // Bosilganda funksiya ishlaydi
}
Spacer()
Image(systemName: "play.circle.fill")
.foregroundColor(.spotifyWhite)
.font(.title)
}
}
.padding(.trailing, 16)
}
.themeColors(isSelected: false)
.cornerRadius(8)
.onTapGesture {
onPlayPressed?()
}
}
}
}
E'tibor bergan bo'lsangiz, tugmalar mantiqini (onPlayPressed) shu komponentning ichiga "qotirib" yozmadik. Uning o'rniga, funksiyani tashqaridan qabul qilib oladigan qilib ochiq qoldirdik.
Bu eng to'g'ri (Best practice) usuldir! Komponent qaysi tugma qanday amal bajarishini o'ylamasligi kerak, uni faqat asosiy ekranga chaqirganimizda tashqaridan biriktiramiz xolos.
Keyingi qismda asosiy ekranni tugatamiz va playlistlarni qo'shamiz!