SwiftUI onTapGesture显示新视图

时间:2020-08-02 16:01:37

标签: view swiftui

我正在使用SwiftUI制作自己的Pizza交付应用程序。我现在陷入困境,因为我不知道如何显示与数组中他自己的索引相关的相同图像视图(包括比萨饼的描述)。除了每行{self.images print("ok")}之外,我希望用户每次从数组中点击图像时都显示带有简短文本描述的相同图像。对我的问题的描述是否足够清楚?如果有人可以帮助我,我将非常感激。非常感谢您阅读。这是代码:

HStack {
    ForEach(images, id: \.id) { post in
        ForEach(0..<1) { _ in
            ImageView(postImages: post)
        }
    }
    Spacer()
}
.onTapGesture {
    self.images
    print("ok")
}
.navigationBarTitle("Choose your Pizza")
.padding()

2 个答案:

答案 0 :(得分:1)

假设您有Item的结构,则需要使其符合Identifiable

struct Item: Identifiable {
    var id: String { name } // needed for `Identifiable`

    let name: String
    let imageName: String
    let description: String
}

然后在您的主视图中:

struct ContentView: View {
    let items = [
        Item(name: "item1", imageName: "circle", description: "some description of item 1"),
        Item(name: "item2", imageName: "circle", description: "some description of item 2"),
        Item(name: "item3", imageName: "circle", description: "some description of item 3"),
    ]

    @State var selectedItem: Item? // <- track the selected item

    var body: some View {
        NavigationView {
            HStack {
                ForEach(items, id: \.id) { item in
                    ImageView(imageName: item.imageName)
                        .onTapGesture { 
                            self.selectedItem = item // select the tapped item
                        }
                }
                Spacer()
            }
            .navigationBarTitle("Choose your Pizza")
            .padding()
        }
        .sheet(item: $selectedItem) { item in // show a new sheet if selectedItem is not `nil`
            DetailView(item: item)
        }
    }
}

如果您有图片的自定义视图:

struct ImageView: View {
    let imageName: String

    var body: some View {
        Image(systemName: imageName)
    }
}

您可以为商品创建详细视图(包括商品说明等):

struct DetailView: View {
    let item: Item

    var body: some View {
        VStack {
            Text(item.name)
            Image(systemName: item.imageName)
            Text(item.description)
        }
    }
}

编辑

这是使用同一视图显示图像或带有描述的图像的另一种方法:

struct ContentView: View {
    @State var items = [
        Item(name: "item1", imageName: "circle", description: "some description of item 1"),
        Item(name: "item2", imageName: "circle", description: "some description of item 2"),
        Item(name: "item3", imageName: "circle", description: "some description of item 3"),
    ]

    var body: some View {
        NavigationView {
            HStack {
                ForEach(items, id: \.self) { item in
                    DetailView(item: item)
                }
                Spacer()
            }
            .navigationBarTitle("Choose your Pizza")
            .padding()
        }
    }
}
struct DetailView: View {
    @State var showDescription = false
    let item: Item

    var body: some View {
        VStack {
            Text(item.name)
            Image(systemName: item.imageName)
            if showDescription {
                Text(item.description)
            }
        }
        .onTapGesture {
            self.showDescription.toggle()
        }
    }
}

并使Item 符合Hashable

struct Item: Hashable

或代替:

ForEach(items, id: \.self)

明确指定id

ForEach(items, id: \.name)

答案 1 :(得分:1)

我也为它的价值took了口。

(顺便说一句,@ pawello2222的答案也是100%正确。实现您所描述的内容的方法不止一种)

我首先创建了一个比萨菜单(使用占位符图像):

Main pizza list view

从菜单中选择一项后,您将进入所选披萨详细信息:

Chosen pizza detail view

我正在使用NavigationViewNavigationLink在视图之间导航。

这是完整的源代码(为了在Swift Playgrounds中获得最佳效果):


import PlaygroundSupport // For running in Swift Playground only
import SwiftUI

// The main pizza listing page (view)
struct PizzaList: View {
    
    // Array of pizza images
    let pizzaImages = [
        Image(systemName: "circle.fill"),
        Image(systemName: "square.fill"),
        Image(systemName: "triangle.fill")
    ]
    
    // Array of pizza descriptions
    let pizzaDescriptions = [
        "Circular Pizza",
        "Square Pizza",
        "Triangle Pizza"
    ]
    
    var body: some View {
        // Wrap in navigation view to be able to switch between "pages"
        NavigationView {
            VStack {
                ForEach(0 ..< pizzaImages.count) { index in
                    // Wrap in navigation link to provide a link to the next "page"
                    NavigationLink(
                        // This is the contents of the chosen pizza page
                        destination: PizzaDetail(
                            pizzaImage: self.pizzaImages[index],
                            description: self.pizzaDescriptions[index]
                        )
                    ) {
                        // This is an item on the main list
                        PizzaRow(
                            pizzaImage: self.pizzaImages[index],
                            description: self.pizzaDescriptions[index]
                        )
                    }
                }
            }
            .navigationBarTitle("Available Pizzas")
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

// Layout for each pizza item on the list
struct PizzaRow: View {
    
    let pizzaImage: Image
    let description: String
    
    var body: some View {
        HStack {
            Spacer()
            
            pizzaImage
                .resizable()
                .aspectRatio(contentMode: .fit)
                .foregroundColor(.orange)
            Spacer()
            
            Text(self.description)
            Spacer()
        }
        .padding()
    }
}

// Layout for the chosen pizza page
struct PizzaDetail: View {
    
    let pizzaImage: Image
    let description: String
    
    var body: some View {
        VStack {
            Spacer()
            Text(description)
                .font(.title)
            
            Spacer()
            
            pizzaImage
                .resizable()
                .aspectRatio(contentMode: .fit)
            Spacer()
        }
        .padding()
        .navigationBarTitle("Your Pizza Choice")
    }
}

// For Playgrounds only
PlaygroundPage.current.setLiveView(PizzaList())