- Published on
SwiftUI crypto app — foydalanuvchi portfelini boshqarish uchun view yaratish
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
SwiftUI crypto app — foydalanuvchi portfelini boshqarish uchun view yaratish
Kursimiz yarmiga yaqinlashib qoldik! Bu darsda foydalanuvchilar o'z portfellarini tahrirlashi uchun yangi ekran yaratamiz. U plus tugmasi bosilganda sheet sifatida paydo bo'ladi va unda tangalar ro'yxati, miqdor kiritish va saqlash imkoniyati bo'ladi.
1. PortfolioView yaratish va sheet-ga ulash
home/views papkasida PortfolioView.swift faylini yaratamiz. Keyin HomeView-da tugmaga sheet bog'laymiz:
// HomeView yuqorida:
@State private var showPortfolio: Bool = false // o'ngga animatsiya
@State private var showPortfolioView: Bool = false // yangi sheet
// Tugma ichida:
.onTapGesture {
if showPortfolio {
showPortfolioView.toggle()
}
}
// Background-ga sheet:
.sheet(isPresented: $showPortfolioView) {
PortfolioView()
.environmentObject(vm) // HomeViewModel-ni yangi muhitga uzatamiz
}
Muhim:
.sheetyangi SwiftUI muhit (environment) hosil qiladi.vm-ni u yerga uzatmasak,PortfolioViewViewModel-ga kira olmaydi.
2. NavigationView va XmarkButton
PortfolioView-da o'z NavigationView-ini yaratishimiz kerak, chunki sheet — alohida muhit:
struct PortfolioView: View {
@EnvironmentObject private var vm: HomeViewModel
@Environment(\.presentationMode) var presentationMode
var body: some View {
NavigationView {
ScrollView {
VStack(alignment: .leading, spacing: 0) {
Text("Hi")
}
}
.navigationTitle("Portfelni tahrirlash")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
XMarkButton() // Qayta ishlatiladigan yopish tugmasi
}
ToolbarItem(placement: .navigationBarTrailing) {
trailingNavBarButtons
}
}
}
}
}
XMarkButton — alohida komponent:
struct XMarkButton: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
Button {
presentationMode.wrappedValue.dismiss()
} label: {
Image(systemName: "xmark")
.font(.headline)
}
}
}
3. CoinLogoView — tanga belgisi komponenti
Har bir tanganing rasmini, belgisini va nomini ko'rsatuvchi kichik komponent:
struct CoinLogoView: View {
let coin: CoinModel
var body: some View {
VStack {
// Tanganing rasmi (CoinImageView oldindan yaratilgan)
CoinImageView(coin: coin)
.frame(width: 50, height: 50)
// Tanga belgisi (masalan: BTC, ETH)
Text(coin.symbol.uppercased())
.font(.headline)
.foregroundColor(Color.theme.accent)
.lineLimit(1)
.minimumScaleFactor(0.5) // kichik bo'lsa — shrink qiladi
// Tanga nomi (masalan: Bitcoin)
Text(coin.name)
.font(.caption)
.foregroundColor(Color.theme.secondaryText)
.lineLimit(2)
.minimumScaleFactor(0.5)
.multilineTextAlignment(.center)
}
}
}
4. Gorizontal tangalar ro'yxati
Qidiruv maydoni va tangalar ro'yxatini PortfolioView-ga qo'shamiz:
// Extension ichida:
private var coinLogoList: some View {
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 10) {
ForEach(vm.allCoins) { coin in
CoinLogoView(coin: coin)
.frame(width: 75)
.padding(4)
.onTapGesture {
withAnimation(.easeIn) {
selectedCoin = coin
}
}
.background(
RoundedRectangle(cornerRadius: 10)
.stroke(
// Tanlangan tanga — yashil chegara, boshqalar shaffof
selectedCoin?.id == coin.id ?
Color.theme.green : Color.clear,
lineWidth: 1
)
)
}
}
.padding(.vertical, 4)
.padding(.leading)
}
}
// View ichida holatlar:
@State private var selectedCoin: CoinModel? = nil
@State private var quantityText: String = ""
@State private var showCheckmark: Bool = false
5. Miqdor kiritish va joriy qiymat hisoblash
Tanga tanlanganda pastda qo'shimcha ma'lumot ko'rsatamiz:
private var portfolioInputSection: some View {
VStack(spacing: 20) {
HStack {
Text("Joriy narx:")
Spacer()
Text(selectedCoin?.currentPrice.asCurrencyWith6Decimals() ?? "")
}
Divider()
HStack {
Text("Portfelda mavjud miqdor:")
Spacer()
TextField("Masalan: 1.4", text: $quantityText)
.multilineTextAlignment(.trailing)
.keyboardType(.decimalPad) // Faqat raqamlar klaviaturasi
}
Divider()
HStack {
Text("Joriy qiymat:")
Spacer()
Text(getCurrentValue().asCurrencyWith2Decimals())
}
}
.animation(.none)
.padding()
.font(.headline)
}
// Miqdor × narx = joriy qiymat
private func getCurrentValue() -> Double {
if let quantity = Double(quantityText) {
return quantity * (selectedCoin?.currentPrice ?? 0)
}
return 0
}
6. Saqlash tugmasi (Save)
Faqat miqdor o'zgarganda ko'rinadigan saqlash tugmasi:
private var trailingNavBarButtons: some View {
HStack(spacing: 10) {
Image(systemName: "checkmark")
.opacity(showCheckmark ? 1.0 : 0.0) // saqlanganda ko'rinadi
Button("SAQLASH") {
saveButtonPressed()
}
// Faqat tanlangan tanga va miqdor o'zgarganda ko'rinadi
.opacity(
selectedCoin != nil &&
selectedCoin?.currentHoldings != Double(quantityText) ?
1.0 : 0.0
)
}
.font(.headline)
}
private func saveButtonPressed() {
guard let coin = selectedCoin else { return }
// Core Data ga saqlash logikasi keyingi darsda
withAnimation(.easeIn) {
showCheckmark = true
removeSelectedCoin()
}
UIApplication.shared.endEditing() // Klaviaturani yopish
// 2 soniyadan keyin checkmark-ni yashiramiz
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation(.easeOut) {
showCheckmark = false
}
}
}
private func removeSelectedCoin() {
selectedCoin = nil
vm.searchText = ""
}
7. NavigationBar sarlavha rangini o'zgartirish
Ilovaning asosiy faylida (SwiftfulCryptoApp.swift) init ichida NavigationBar rangini belgilaymiz:
init() {
// Katta sarlavha rangi
UINavigationBar.appearance().largeTitleTextAttributes = [
.foregroundColor: UIColor(Color.theme.accent)
]
// Oddiy sarlavha rangi
UINavigationBar.appearance().titleTextAttributes = [
.foregroundColor: UIColor(Color.theme.accent)
]
}
Natija
Simulatorda ilovani ishga tushiring:
- Portfel tabiga o'ting → plus tugmasini bosing
- Yangi sheet ochiladi — tangalar gorizontal ro'yxatda
- Biror tangani bosing — yashil chegara paydo bo'ladi
- Miqdor kiriting — SAQLASH tugmasi paydo bo'ladi
- Saqlash bosilganda ✓ belgisi chiqib, 2 soniyada g'oyib bo'ladi
Keyingi darsda Core Data yordamida portfelni haqiqatda saqlaymiz! 🚀