SwiftUI onTapGesture отображает новое представление - PullRequest
1 голос
/ 02 августа 2020

Я использую SwiftUI для создания собственного приложения для доставки пиццы. Я застрял, потому что не знаю, как я могу отобразить то же представление изображения (включая описание пиццы), связанное с его собственным индексом из массива. Вместо строк {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 ]

1 голос
/ 03 августа 2020

Я тоже нанёс ему удар, чего бы он ни стоил.

(Кстати, ответ @ pawello2222 также на 100% правильный. Есть несколько способов добиться того, что вы описали)

Сначала я создал меню пиццы (используя изображения-заполнители):

Основной вид списка пиццы

Выбрав элемент из меню, вы попадете к выбранной пицце подробно:

Детальный вид выбранной пиццы

Я использую NavigationView и NavigationLink для перехода между видами.

Вот полный исходный код код (для достижения наилучших результатов запускайте в 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())
0 голосов
/ 03 августа 2020

Предполагая, что у вас есть структура для 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)
    }
}

вы можете создать подробный вид для вашего элемента (с описанием элемента и c):

struct DetailView: View {
    let item: Item

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

EDIT

Вот другой подход с использованием одного и того же вида для отображения изображения или изображения с его описанием:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...