Published on

Spotify kloni (1-qism): Asosiy ekran va Header qismi

Authors

Spotify klonini boshlaymiz

Nihoyat haqiqiy va qiziqarli ishlarga keldik! Ushbu darsda dunyodagi eng mashhur musiqa ilovasi bo'lmish Spotify ning asosiy sahifasini (Home Screen) yig'ishni boshlaymiz.

Bu ekranda har xil turdagi murakkab qatorlar (rows), animatsiyalar, rasmlar hamda foydalanuvchi sahifani pastga tushirganda (scroll qilganda) tepaga yopishib qoladigan qiziqarli Sarlavha (Header) bor. Biz shularni bosqichma-bosqich yig'amiz.

1. Rasm va ranglarni sozlash

Birinchi o'rinda loyihamizning Assets.xcassets bo'limiga kirib, Spotify ga xos bo'lgan ranglarni qo'shib olamiz:

  • SpotifyBlack: Hex #121212
  • SpotifyDarkGray: Hex #212121
  • SpotifyGreen: Hex #1DB954
  • SpotifyLightGray: Hex #B3B3B3
  • SpotifyWhite: Hex #E1ECE3 (Toza oq emas, ko'zni charchatmaydigan oq)

2. Kategoriyalar uchun maxsus cell (katakcha)

Yuqori qismda "All", "Music", "Podcasts" va "Audiobooks" kabi tugmalar bor. Ular tanlangan holatiga qarab rangi o'zgaradi. Bunga alohida komponent SpotifyCategoryCell yaratamiz.

Shuningdek, bu tugmalarni shunchaki qattiq kod bilan emas, tartibli tarzda ishlatish uchun bitta oddiy Enum qo'shamiz:

enum Category: String, CaseIterable {
    case all = "All"
    case music = "Music"
    case podcasts = "Podcasts"
    case audiobooks = "Audiobooks"
}

3. Pinned Header (Qotib turuvchi sarlavha)

Agar siz an'anaviy SwiftUI dan foydalansangiz, sarlavhani tepada qotirib qo'yish juda asabni buzadigan muammo bo'lishi mumkin. Ammo LazyVStack yordamida bu osongina hal qilinadi.

Asosiy SpotifyHomeView ekranimizni shunday yig'amiz:

import SwiftUI

struct SpotifyHomeView: View {
    @State private var currentCategory: Category = .all

    var body: some View {
        ZStack {
            Color.spotifyBlack.ignoresSafeArea()

            ScrollView(.vertical, showsIndicators: false) {
                LazyVStack(spacing: 1, pinnedViews: [.sectionHeaders]) {
                    Section {
                        // Asosiy kontentlar shuning ichida bo'ladi (Pleylistlar va h.k.)
                        ForEach(0..<20) { _ in
                            Rectangle()
                                .fill(Color.red)
                                .frame(height: 200)
                        }
                    } header: {
                        headerView
                    }
                }
                .padding(.top, 8)
            }
            .clipped()
        }
    }

    // Header qismini kod ko'payib ketmasligi uchun alohida var qilib oldik
    private var headerView: some View {
        HStack(spacing: 0) {
            ImageLoaderView() // Profil rasmi
                .frame(width: 35, height: 35)
                .clipShape(Circle())

            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 8) {
                    ForEach(Category.allCases, id: \.self) { category in
                        SpotifyCategoryCell(
                            title: category.rawValue,
                            isSelected: category == currentCategory
                        )
                        .onTapGesture {
                            currentCategory = category
                        }
                    }
                }
                .padding(.horizontal, 16)
            }
        }
        .padding(.vertical, 24)
        .padding(.leading, 8)
        .background(Color.spotifyBlack)
    }
}

Bu kodda .pinnedViews: [.sectionHeaders] jumlasi ekrandagi Section ning faqatgina Header qismini tepada qotirib ushlab turadi.

Ana endi ekranda chiroyli profil rasmi va ishlaydigan kategoriyalar menyusi paydo bo'ldi. Keyingi darslarda pleylistlar va boshqa qatorlarni to'ldirishda davom etamiz!

Buy mea coffee