Published on

SwiftUI crypto app — ma'lumotlarni grid formatida va statistika sifatida ko'rsatish

Authors

SwiftUI crypto app — ma'lumotlarni grid formatida va statistika sifatida ko'rsatish

Oldingi darsda DetailViewModel va CoinDetailDataService yordamida ma'lumotlarni yuklab oldik. Bu darsda ularni ekranda ko'rsatamiz. LazyVGrid — ikkita ustunli grid — statistikalarni chiroyli va samarali ko'rsatadi.


1. DetailView asosiy tuzilmasi

import SwiftUI

struct DetailView: View {
    @StateObject private var vm: DetailViewModel

    private let columns: [GridItem] = [
        GridItem(.flexible()),
        GridItem(.flexible())
    ]
    private let spacing: CGFloat = 30

    init(coin: CoinModel) {
        _vm = StateObject(wrappedValue: DetailViewModel(coin: coin))
    }

    var body: some View {
        ScrollView {
            VStack {
                // Yuqori bo'lim (grafik — keyingi darsda qo'shiladi)
                Text("")
                    .frame(height: 150)

                VStack(spacing: 20) {
                    overviewTitle
                    Divider()
                    descriptionSection    // Tavsif matni
                    overviewGrid
                    additionalTitle
                    Divider()
                    additionalGrid
                    websiteSection        // Havolalar
                }
                .padding()
            }
        }
        .navigationTitle(vm.coin.name)
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                navigationBarTrailingItems
            }
        }
    }
}

2. Overview va qo'shimcha statistika gridi

extension DetailView {

    private var overviewTitle: some View {
        Text("Ko'rinish")
            .font(.title)
            .bold()
            .foregroundColor(Color.theme.accent)
            .frame(maxWidth: .infinity, alignment: .leading)
    }

    private var additionalTitle: some View {
        Text("Qo'shimcha ma'lumotlar")
            .font(.title)
            .bold()
            .foregroundColor(Color.theme.accent)
            .frame(maxWidth: .infinity, alignment: .leading)
    }

    // Overview statistikasi: narx, bozor kap, reyting, hajm
    private var overviewGrid: some View {
        LazyVGrid(
            columns: columns,
            alignment: .leading,
            spacing: spacing,
            pinnedViews: []
        ) {
            ForEach(vm.overviewStatistics) { stat in
                StatisticView(stat: stat)
            }
        }
    }

    // Qo'shimcha statistika: yuqori/past narx, bloklash vaqti va hokazo
    private var additionalGrid: some View {
        LazyVGrid(
            columns: columns,
            alignment: .leading,
            spacing: spacing,
            pinnedViews: []
        ) {
            ForEach(vm.additionalStatistics) { stat in
                StatisticView(stat: stat)
            }
        }
    }
}

LazyVGrid nima? Ikki parametr asosiy: columns va spacing. GridItem(.flexible()) — ikkita ustun teng kenglikda bo'linadi. LazyVGrid ekranda ko'rinadigan elementlarnigina yaratadi — bu katta ro'yxatlarda samarali.


3. Tanga tavsifi (description) bo'limi

CoinGecko API-dan kelgan tavsif matnini ko'rsatamiz. U uzun bo'lgani uchun — "ko'proq ko'rsatish" tugmasi qo'shamiz:

extension DetailView {

    @State private var showFullDescription: Bool = false

    private var descriptionSection: some View {
        ZStack {
            if let coinDescription = vm.coinDescription, !coinDescription.isEmpty {
                VStack(alignment: .leading) {
                    Text(coinDescription)
                        .lineLimit(showFullDescription ? nil : 3)  // nil = cheksiz qator
                        .font(.callout)
                        .foregroundColor(Color.theme.secondaryText)

                    Button {
                        withAnimation(.easeInOut) {
                            showFullDescription.toggle()
                        }
                    } label: {
                        Text(showFullDescription ? "kamroq ko'rsatish ▲" : "ko'proq ko'rsatish ▼")
                            .font(.caption)
                            .bold()
                            .padding(.vertical, 4)
                    }
                    .accentColor(.blue)
                }
                .frame(maxWidth: .infinity, alignment: .leading)
            }
        }
    }
}

Nima uchun lineLimit(nil)? lineLimit(3) — 3 qatorgacha, lineLimit(nil) — cheksiz. Tugmani bosganda ular almashinadi.


4. NavigationBar-dagi tanga belgisi va nomi

private var navigationBarTrailingItems: some View {
    HStack {
        Text(vm.coin.symbol.uppercased())
            .font(.headline)
            .foregroundColor(Color.theme.secondaryText)
        CoinImageView(coin: vm.coin)
            .frame(width: 25, height: 25)
    }
}

5. Veb-sayt va Reddit havolalari

private var websiteSection: some View {
    VStack(alignment: .leading, spacing: 20) {
        if let websiteString = vm.websiteURL,
           let url = URL(string: websiteString) {
            Link("Rasmiy veb-sayt", destination: url)
        }

        if let redditString = vm.redditURL,
           let url = URL(string: redditString) {
            Link("Reddit", destination: url)
        }
    }
    .accentColor(.blue)
    .frame(maxWidth: .infinity, alignment: .leading)
    .font(.headline)
}

Link — SwiftUI-ning ichki brauzer yechimi. Bosilganda Safari ochilmaydi — balki ilovaning ichida SFSafariViewController ochiladi (yoki standart brauzerga o'tadi). Bu foydalanuvchi uchun qulay.


6. DetailViewModel-da coin saqlash

DetailViewModel-da coin xususiyatini @Published qilish kerak — NavigationBar-ga uzatish uchun:

class DetailViewModel: ObservableObject {
    @Published var overviewStatistics: [StatisticModel] = []
    @Published var additionalStatistics: [StatisticModel] = []
    @Published var coinDescription: String? = nil
    @Published var websiteURL: String? = nil
    @Published var redditURL: String? = nil

    let coin: CoinModel  // NavigationBar uchun ochiq
    // ...
}

7. Natija

Ilovada Bitcoin yoki boshqa tangani bosing:

  • Ko'rinish bo'limi: joriy narx, bozor kap, reyting, hajm — ikkita ustunda
  • Tavsif: qisqa ko'rinish, "ko'proq ko'rsatish" tugmasi
  • Qo'shimcha: 24s maksimal/minimal narx, foiz o'zgarishi, bloklash vaqti, hashing algoritmi
  • Havolalar: rasmiy veb-sayt va Reddit
Bitcoin
Joriy narx: $43,250.12    Bozor kap: $842.5Bn
Reyting: 1                24s hajm: $28.3Bn

Qo'shimcha ma'lumotlar
24s maksimal: $44,100.00  24s minimal: $42,800.00
Narx o'zgarishi: +$1,250  Bozor kap o'zg: +$15.2Bn
Blok vaqti: 10            Hashing: SHA-256

"Ma'lumotlar bir joyda chiroyli grid shaklida joylashgan. LazyVGrid-ning kuchli tomoni shunda — element sonini o'zgartirsak, view avtomatik yangilanadi. Qo'shimcha view kodi yozish shart emas!"

Keyingi darsda biz ilovaning yuqori qismiga narx grafigini qo'shamiz. 🚀

Buy mea coffee