- Published on
Spotify kloni (4-qism): Pleylist ekrani va Stretchy Header
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Yangi Ekranga o'tamiz: Pleylist oynasi
Keling, foydalanuvchi asosiy (Home) ekrandan biror pleylistni bossa ochiladigan ikkinchi oynani yasashni boshlaymiz. Buni SpotifyPlaylistView deb nomlaymiz.
Bu ekranning eng qiziq va qiyin joyi shundaki, tepada katta rasm bor. Agar barmoqni pastga tortsangiz rasm kattalashib chuziladi (Stretchy Header), tepaga sursangiz rasm sekin yo'qolib o'rniga Navigation Bar paydo bo'ladi.
1. PlaylistHeaderCell va stretchy header
Avval Components papkamizda PlaylistHeaderCell degan fayl yaratib, tepada turuvchi katta rasmni sozlab olamiz:
import SwiftUI
import SwiftfulUI // Stretchy header uchun o'zimizning kutubxona
struct PlaylistHeaderCell: View {
var height: CGFloat = 300
var title: String = "Subtitle goes here"
var subtitle: String = "Title goes here"
var imageName: String = "https://picsum.photos/600/600"
var shadowColor: Color = .spotifyBlack.opacity(0.8)
var body: some View {
Rectangle()
.opacity(0)
.overlay(
ImageLoaderView(urlString: imageName)
)
.overlay(
VStack(alignment: .leading, spacing: 8) {
Text(subtitle)
.font(.headline)
Text(title)
.font(.largeTitle)
.fontWeight(.bold)
}
.foregroundColor(.spotifyWhite)
.padding(16)
.frame(maxWidth: .infinity, alignment: .leading)
.background(
LinearGradient(
colors: [shadowColor.opacity(0), shadowColor],
startPoint: .top,
endPoint: .bottom
)
)
, alignment: .bottomLeading
)
.asStretchyHeader(startingHeight: height) // Asosiy sehr shu yerda!
}
}
E'tibor bering: Rasm ustiga oq tekst yozsangiz, agar rasm ham oqish bo'lsa tekstni umuman o'qib bo'lmay qoladi. Shuning uchun tekstning orqasiga (
background) yengilLinearGradient(shaffofdan qoraga qarab) berib yubordik. Bu dizaynni juda professional ko'rsatadi.
Koddagi .asStretchyHeader() modifikatori SwiftfulUI paketi orqali avtomatik ishlaydi va ScrollView bilan birga rasmning cho'zilishini ta'minlaydi.
2. Pleylist tavsifi (Description Cell)
Rasmning darhol pastida Spotify pleylistlariga xos bo'lgan "Made for User" degan yozuv va juda ko'p mayda tugmalar (Share, Download, Shuffle, Play) keladi. Bu qism uchun alohida PlaylistDescriptionCell yaratamiz.
Bunda tugmalarni hammasini HStack ichida yonma-yon qilib joylaymiz, va Play tugmasini kattaroq hamda yashil qilib olamiz:
import SwiftUI
struct PlaylistDescriptionCell: View {
var descriptionText: String = "Some description goes here"
var userName: String = "Nick"
var subheadline: String = "Some headline goes here"
// Barcha tugmalarning action'larini ochiq qoldiramiz
var onAddToPlaylistPressed: (() -> Void)? = nil
var onDownloadPressed: (() -> Void)? = nil
var onSharePressed: (() -> Void)? = nil
var onEllipsisPressed: (() -> Void)? = nil
var onShufflePressed: (() -> Void)? = nil
var onPlayPressed: (() -> Void)? = nil
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text(descriptionText)
.foregroundColor(.spotifyLightGray)
.frame(maxWidth: .infinity, alignment: .leading)
// "Made for User" qismi
HStack(spacing: 8) {
Image(systemName: "applelogo")
.foregroundColor(.spotifyGreen)
.font(.title3)
Text("Made for ")
+
Text(userName)
.bold()
.foregroundColor(.spotifyWhite)
}
.font(.callout)
.fontWeight(.medium)
Text(subheadline)
.foregroundColor(.spotifyLightGray)
buttonsRow
}
}
// Tugmalar qatori
private var buttonsRow: some View {
HStack(spacing: 0) {
HStack(spacing: 0) {
Image(systemName: "plus.circle")
.font(.title2)
.padding(8)
.background(Color.black.opacity(0.001))
.onTapGesture { onAddToPlaylistPressed?() }
// qolgan tugmalar ham shunday...
}
.frame(maxWidth: .infinity, alignment: .leading)
HStack(spacing: 8) {
Image(systemName: "shuffle")
.font(.system(size: 24))
.onTapGesture { onShufflePressed?() }
Image(systemName: "play.circle.fill")
.font(.system(size: 46))
.onTapGesture { onPlayPressed?() }
}
.foregroundColor(.spotifyGreen)
}
}
}
Bu darsimizda katta ma'lumotlarni qanday qilib qismlarga (Cells) ajratishni o'rgandik. Keyingi darsda ushbu Pleylist oynasini haqiqiy musiqalar qatori bilan to'ldiramiz va Sarlavha animatsiyasini tugatamiz.