SwiftUI로 무작정 만들기 3탄, 카드형 리스트

해류·2022년 6월 7일
0
post-thumbnail

list를 이용해 StockCardList를 만들어 보았다.

StockList

import SwiftUI

struct StockList: View {
    
    var stockList: [StockModel] = Stocks.list
    
    var body: some View {
        List(stockList, id: \.id) { stock in
            StockUI(rank: stock.rank, imageName: stock.imageName, name: stock.name, price: convertToCurrencyFormat(price: stock.price), diff: stock.diff)
        }
        .background(.black)
        .listStyle(PlainListStyle())
    }
}

struct StockList_Previews: PreviewProvider {
    static var previews: some View {
        StockList()
    }
}

extension View {
    func convertToCurrencyFormat(price: Int) -> String {
        let numberFormatter = NumberFormatter()
        //숫자 세자리마다 , 추가
        numberFormatter.numberStyle = .decimal
        //소수점 이하 제거
//        numberFormatter.maximumFractionDigits = 0
        let result = numberFormatter.string(from: NSNumber(value: price)) ?? ""
        return result
    }
}

StockUI(Card형)

import SwiftUI

struct StockUI: View {

    //String 값을 저장할 경우, 값이 없을 때, nil을 반환 하기 때문에
    //let name = UserDefaults.standard.string(forKey: "name") ?? "" 처럼 옵셔널 바인딩 필수!
    
    @State var isLikeStock: Bool = UserDefaults.standard.bool(forKey: "isLikeStock_key")
//    @AppStorage("isLikeStock_key") var isLikeStock: Bool = UserDefaults.standard.bool(forKey: "isLikeStock_key")
    
    var rank: Int
    var imageName: String
    var name: String
    var price: String
    var diff: Double

    var body: some View {
        HStack {
            Text("\(rank)")
                .fontWeight(.bold)
                .foregroundColor(.blue)
                .frame(width: 20, alignment: .center)
                .padding(.trailing, 10)
            Image(imageName)
                .resizable()
                .frame(width: 45, height: 45, alignment: .center)
            VStack(alignment: .leading, spacing: 5) {
                Text(name)
                    .font(.system(size: 20, weight: .bold))
                    .foregroundColor(.white)
                HStack {
                    Text("\(price) 원")
                        .font(.caption)
                        .foregroundColor(.gray)
                    //String(format: "%.2f", value)는 소수점 2째 자리까지 value 갑을 나타낸다는 의미
                    Text("\(String(format: "%.2f", diff))%")
                        .font(.caption)
                        .foregroundColor(diff >= 0 ? .blue : .red)
                }
            }
            .padding(.leading, 10)
            Spacer()
            Image(systemName: "heart.fill")
                .resizable()
                .scaledToFit()
                .frame(width: 30)
                .foregroundColor(isLikeStock ? .red : .gray)
                .padding(.trailing)
                .onTapGesture {
                    isLikeStock.toggle()
                    UserDefaults.standard.setValue(isLikeStock, forKey: "isLikeStock_key")
                }
        }
        .background(.black)
        //리스트의 백그라운드 색상을 변경 .clear를 이용하면 배경을 그대로 투영.
        .listRowBackground(Color.clear)
        //리스트의 구분선을 숨기는 코드
        .listRowSeparator(.hidden)
        .padding(EdgeInsets(top: 15, leading: 0, bottom: 7, trailing: 0))
    }
}

struct StockUI_Previews: PreviewProvider {
    static var previews: some View {
        StockUI(rank: 1, imageName: "AAPL", name: "애플", price: "0000", diff: 0.000)
            .background(.black)
    }

StockModel

import Foundation

//list와 grid 같은 목록형을 작성할 때는 Identifiable과 개체에 대한 id가 필요함
struct StockModel: Identifiable {
    let id = UUID()
    let rank: Int
    let imageName: String
    let name: String
    let price: Int
    let diff: Double
}

struct Stocks {
    static let list: [StockModel] = [
        StockModel(rank: 1, imageName: "TSLA", name: "테슬라", price: 1_238_631, diff: 0.04),
        StockModel(rank: 2, imageName: "AAPL", name: "애플", price: 238_631, diff: 1.04),
        StockModel(rank: 3, imageName: "NFLX", name: "넷플릭스", price: 438_631, diff: -0.04),
        StockModel(rank: 4, imageName: "GOOG", name: "알파벳 A", price: 3_176_631, diff: 0.04),
        StockModel(rank: 5, imageName: "AMZN", name: "아마존", price: 3_538_631, diff: 0.04),
        StockModel(rank: 6, imageName: "NIKE", name: "나이키", price: 158_631, diff: 0.04),
        StockModel(rank: 7, imageName: "DIS", name: "디즈니", price: 138_631, diff: 0.04),
        StockModel(rank: 8, imageName: "TSLA", name: "테슬라", price: 1_238_631, diff: 0.04),
        StockModel(rank: 9, imageName: "AAPL", name: "애플", price: 238_631, diff: 1.04),
        StockModel(rank: 10, imageName: "NFLX", name: "넷플릭스", price: 438_631, diff: -0.04),
        StockModel(rank: 11, imageName: "GOOG", name: "알파벳 A", price: 3_176_631, diff: 0.04),
        StockModel(rank: 12, imageName: "AMZN", name: "아마존", price: 3_538_631, diff: 0.04),
        StockModel(rank: 13, imageName: "NIKE", name: "나이키", price: 158_631, diff: 0.04),
        StockModel(rank: 14, imageName: "DIS", name: "디즈니", price: 138_631, diff: 0.04),
    ]
}
profile
iOS 개발자 지망생

0개의 댓글