首页 > 解决方案 > 如何在 SwiftUI 中使用 .onTapGesture 在来自两个不同 api(没有 Button\TextField)的两个列表中使用 ScrollViewReader?

问题描述

我有一个项目,其中两个不同银行的列表显示货币汇率。我希望当我在第一个列表中选择货币时,第二个列表将自动滚动到相同的货币。我看到了带有按钮的教程,但这不是我需要的。我想使用 onTapGesture,但我不知道如何以正确的方式参与它。ExchangeRatesPB(ccy) 和 ExchangeRatesNBU(cc) 有一些货币的简称:“USD”、“EUR”、“RUR”。无论如何感谢您的帮助。

struct ContentView: View {
        @State private var date = Date()
        @State var currenciesPB: [ExchangeRatesPB] = []
        @State var currenciesNBU: [ExchangeRatesNBU] = []
        
        @State var scrollToCurrency: String = ""
        
        var body: some View {
            ZStack {
                Color(.systemGray6)
                    .edgesIgnoringSafeArea(.all)
                VStack {
                    HStack {
                        Spacer(minLength: 110)
                        Text("Exchange rates")
                            .font(.title2)
                            .padding()
                        
                        Spacer()
                        Image(systemName: "chart.bar.xaxis")
                            .font(.title)
                            .padding()
                    }
                    .foregroundColor(.white)
                    .padding(.top)
                    .background(Color.init(#colorLiteral(red: 0.4558259845, green: 0.5886077285, blue: 0.5515387654, alpha: 1)))
                    .edgesIgnoringSafeArea(.top)
                    
                    //PB
                    VStack {
                        HStack {
                            Text("PrivatBank")
                                .foregroundColor(Color.init(#colorLiteral(red: 0.3549223542, green: 0.3776315749, blue: 0.4196012616, alpha: 1)))
                            Spacer(minLength: 100)
                            
                            Image(systemName: "calendar")
                                .foregroundColor(.gray)
                            DatePicker("", selection: $date, displayedComponents: .date)
                        }
                        .font(.title2)
                        .padding(10)
                        
                        HStack(spacing: 60) {
                            Text("Currency")
                            Text("Purchase")
                            Text("Sale")
                        } .foregroundColor(.gray)
                        VStack {
                            //                        ScrollView {
                            List(currenciesPB, id: \.self) { currencyPB in
                                VStack {
                                    HStack(spacing: 60) {
                                        Text(currencyPB.ccy)
                                            .id(currencyPB.ccy)
                                        Text(currencyPB.sale)
                                        Text(currencyPB.buy)
                                    }
                                   // .onTapGesture {
                                        //scrollToCurrency = currencyPB.ccy
                                        //print(scrollToCurrency)
                                   // }
                                    .foregroundColor(Color.init(#colorLiteral(red: 0.3549223542, green: 0.3776315749, blue: 0.4196012616, alpha: 1)))
                                }
                            }
                            //                        }
                            .padding(.top)
                            .onAppear() {
                                ApiPB().getCurrency { (currenciesPB) in
                                    self.currenciesPB = currenciesPB
                                }
                            }
                        }
                    }
                    
                    //NBU
                    VStack {
                        HStack {
                            Text("NBU")
                                .foregroundColor(Color.init(#colorLiteral(red: 0.3549223542, green: 0.3776315749, blue: 0.4196012616, alpha: 1)))
                            Spacer(minLength: 150)
                            
                            Image(systemName: "calendar")
                                .foregroundColor(.gray)
                            DatePicker("", selection: $date, displayedComponents: .date)
                        }
                        .font(.title2)
                        .padding(10)
                        //                    ScrollView {
                        ScrollViewReader { value in
                            VStack {
                                List(currenciesNBU, id: \.self) { currencyNBU in
                                    VStack {
                                        HStack(spacing: 50) {
                                            Text(currencyNBU.txt)
                                            Spacer()
                                            VStack {
                                                HStack {
                                                    Text(String(currencyNBU.rate))
                                                    Text("UAH")
                                                }
                                            }
                                        }
                                        .listRowBackground(Color(.systemGray6))
                                        .foregroundColor(Color.init(#colorLiteral(red: 0.3549223542, green: 0.3776315749, blue: 0.4196012616, alpha: 1)))
                                    }
                                }
                                .onChange(of: scrollToCurrency) { _ in
                                    value.scrollTo(scrollToCurrency, anchor: .top)
                                }
                                .padding(.top)
                                .onAppear() {
                                    ApiNBU().getCurrency { (currenciesNBU) in
                                        self.currenciesNBU = currenciesNBU
                                    }
                                }
                            }
                            
                        }
                        //                    }
                    }
                }
            }
        }
    }
    
    struct ExchangeRatesPB: Codable, Hashable {
        let ccy: String
        let base_ccy: String
        var buy: String
        var sale: String
    }
    
    class ApiPB {
        func getCurrency(completion: @escaping ([ExchangeRatesPB]) -> ()) {
            guard let url = URL(string: "https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5") else { return }
            
            URLSession.shared.dataTask(with: url) { (data, _, _) in
                let currenciesPB = try! JSONDecoder().decode([ExchangeRatesPB].self, from: data!)
                DispatchQueue.main.sync {
                    completion(currenciesPB)
                }
            }
            .resume()
        }
    }
    
    struct ExchangeRatesNBU: Codable, Hashable {
        let r030: Int
        let txt: String
        var rate: Double
        var cc: String
    }
    
    class ApiNBU {
        func getCurrency(completion: @escaping ([ExchangeRatesNBU]) -> ()) {
            guard let url = URL(string: "https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date=20200302&json") else { return }
            URLSession.shared.dataTask(with: url) { (data, _, _) in
                let currenciesNBU = try! JSONDecoder().decode([ExchangeRatesNBU].self, from: data!)
                DispatchQueue.main.sync {
                    completion(currenciesNBU)
                }
            }
            .resume()
        }
    }

标签: swiftuiswiftui-ontapgesturescrollviewreader

解决方案


你的方法很好,你只错过了一次。中的第一个参数scrollTo()id,当您创建列表时,您指定selfid. 因此,要滚动到该元素,您需要传递要滚动到的整个对象,或者只需id像这样更改您的列表:

List(currenciesNBU, id: \.cc)

推荐阅读