如何将数组值放入按钮列表中,这些按钮将基于所单击的内容打开新视图

时间:2019-11-11 17:48:21

标签: swift swiftui

如您所见,HStack非常冗余。 我想要一个包含图像和文本的某种类型的数组 但是我不知道如何将该数组放入列表中,更重要的是,我不知道如何识别单击了数组中的哪个元素并根据单击的内容打开了新视图

struct ContentView: View {
    var body: some View {
        ZStack {
            NavigationView {
                List {

// as you can see the HStack is very redundant.
// I want to have an array of some type that contains both the image and the text
// But I do not know how to put that array into the list, more importantly I do not know how to recognize which element in the array was clicked and open a new view based on what is clicked
                    HStack {
                        Image("someImage")
                        .resizable()
                            .frame(width: 50, height: 50, alignment: .leading)
                        .clipShape(Circle())
                        NavigationLink (destination: SomeView()) {
                            Text("SomeText").foregroundColor(.gray)
                            .bold()
                        }
                    }
                    HStack {
                        Image("Image2")
                            .resizable()
                            .clipShape(Circle())
                            .frame(width: 50, height: 50, alignment: .leading)
                        NavigationLink(destination: image2()) {
                            Text("text2").foregroundColor(.gray)
                            .bold()
                        }
                    }
                    HStack {
                        Image("image3")
                            .resizable()
                            .clipShape(Circle())
                            .frame(width: 50, height: 50, alignment: .leading)
                        NavigationLink(destination: view3()) {
                            Text("view3").foregroundColor(.gray)
                            .bold()
                        }
                    }
                }.navigationBarTitle("list")
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您可以这样做:

public struct ImageTextView<Destination> : Hashable where Destination: View {

    public static func == (lhs: ImageTextView<Destination>, rhs: ImageTextView<Destination>) -> Bool {
        return lhs.uuid == rhs.uuid
    }

    public var hashValue: Int {
           return uuid.hashValue
       }

    var uuid = UUID().uuidString
    var image: Image
    var text : String
    var destination: Destination

    init(image: Image, text: String, destination: Destination) {
        self.image = image
        self.text = text
        self.destination = destination
    }
}

struct SomeView: View {

    var body: some View {
        Text ("navigation target")
    }
}

let rows  = [
    ImageTextView(image: Image("someImage"), text: "SomeText", destination: SomeView())
//    ImageTextView(image: Image("image2"), text: "text2", destination: SomeView())
     ]

struct ContentView: View {
    var body: some View {
        ZStack {
            NavigationView {
                List {

// as you can see the HStack is very redundant.
// I want to have an array of some type that contains both the image and the text
// But I do not know how to put that array into the list, more importantly I do not know how to recognize which element in the array was clicked and open a new view based on what is clicked
                    ForEach (rows, id: \.self) { row  in

                        HStack {
                            row.image
                                .resizable()
                                .frame(width: 50, height: 50, alignment: .leading)
                                .clipShape(Circle())
                            NavigationLink (destination: SomeView()) {
                                Text(row.text).foregroundColor(.gray)
                                    .bold()
                            }
                        }
                    }
                }.navigationBarTitle("list")
            }
        }
    }
}

答案 1 :(得分:1)

您将需要3个不同的数组或一个模型,由于您的问题是关于数组的,因此我将使用第一种使用数组的方法进行演示。

import SwiftUI

struct ContentView: View {
    let views: [AnyView] = [AnyView(SomeView()), AnyView(Image2()), AnyView(View3())]
    var body: some View {
        NavigationView {
            List {
                ForEach(0...2, id: \.self) { index in
                    NavigationLink (destination: self.views[index]) {
                        ListRowView(index: index)
                    }
                }
            }.navigationBarTitle("List")
        }
    }
}



#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

struct ListRowView: View {
    var index: Int
    let imageNames: [String] = ["cart","star","book"]
    let textList: [String] = ["SomeText","text2","view3"]
    var body: some View {
        HStack {
            Image(systemName: self.imageNames[index])
                .resizable()
                .clipShape(Circle())
                .frame(width: 50, height: 50, alignment: .leading)
            Text(self.textList[index])
                .foregroundColor(.gray)
                .bold()
        }
    }
}

struct SomeView: View {
    var body: some View {
        Text("SomeView")
            .foregroundColor(.gray)
            .bold()
     }
}

struct Image2: View {
    var body: some View {
        Text("Image2")
            .foregroundColor(.gray)
            .bold()
     }
}

struct View3: View {
    var body: some View {
        Text("View3")
            .foregroundColor(.gray)
            .bold()
     }
}

第一个数组表示您的目标视图,其类型为AnyView,另外两个数组是常规的String数组,分别表示图像名称和文本。我仅将systemName图像用于演示,您可以使用资产中的图像名称。

我希望这是您要寻找的,如果答案对您有用,请接受它作为答案。也不要犹豫,发表评论!