Почему контекстное меню SwiftUI отображает все строки в предварительном просмотре? - PullRequest
5 голосов
/ 07 февраля 2020

У меня есть сложное представление в строке списка:

var body: some View {
        VStack {
            VStack {
                FullWidthImageView(ad)

                HStack {
                    Text("\(self.price) \(self.ad.currency!)")
                            .font(.headline)
                    Spacer()
                    SwiftUI.Image(systemName: "heart")
                }
                        .padding([.top, .leading, .trailing], 10.0)

Где FullWidthImageView - представление с определенным модификатором contexMenu. Но когда я долго нажимаю на изображение, я вижу не только изображение в предварительном просмотре, но и весь вид строки.

image image

Никакого другого contextMenu ни в одном элементе нет.

Как сделать предварительный просмотр в контексте только с изображением?

UPD. Здесь - простой код, иллюстрирующий проблему

Ответы [ 2 ]

3 голосов
/ 07 февраля 2020

Вот код (смоделированный по вашему сценарию), который работает, ie. для предварительного просмотра контекстного меню отображается только изображение (протестировано с Xcode 11.3 +).

enter image description here

struct FullWidthImageView: View {
    var body: some View {
        Image("auto")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 200)
            .contextMenu(ContextMenu() {
                Button("Ok") {}
            })
    }
}

struct TestContextMenu: View {
    var body: some View {
        VStack {
            VStack {
                FullWidthImageView()

                HStack {
                    Text("100 $")
                        .font(.headline)
                    Spacer()
                    Image(systemName: "heart")
                }
                .padding([.top, .leading, .trailing], 10.0)

            }
        }
    }
}
2 голосов
/ 07 февраля 2020

Мы не имеем ни малейшего представления, почему в вашем случае это не сработает, пока мы не увидим ваш FullWidthImageView и как вы создадите контекстное меню. Ответ Аспери - рабочий пример, и это правильно сделано! Но действительно ли это объяснило вашу проблему?

Проблема в том, что при применении модификатора .contextMenu только к некоторой части вашего представления (как в вашем примере) мы должны быть осторожны.

Давайте рассмотрим пример.

import SwiftUI

struct FullWidthImageView: View {
    @ObservedObject var model = modelStore
    var body: some View {
        VStack {
            Image(systemName: model.toggle ? "pencil.and.outline" : "trash")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 200)
        }.contextMenu(ContextMenu {
            Button(action: {
                self.model.toggle.toggle()
            }) {
                HStack {
                    Text("toggle image to?")
                    Image(systemName: model.toggle ? "trash" : "pencil.and.outline")
                }
            }
            Button("No") {}
        })
    }
}

class Model:ObservableObject {
    @Published var toggle = false
}

let modelStore = Model()

struct ContentView: View {
    @ObservedObject var model = modelStore
    var body: some View {
        VStack {
            FullWidthImageView()
            Text("Long press the image to change it").bold()
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

во время работы, измененное представление «контекстного меню» выглядит как «stati c» !

enter image description here

Да, при длительном нажатии вы видите изображение tra sh, даже если оно корректно обновляется, пока вы закрываете контекстное представление. При каждом долгом нажатии вы видите только тра sh

Как сделать его динамичным c? Мне нужно, чтобы изображение было таким же, как на моем «главном представлении!» Здесь у нас есть .id модификатор . Давайте посмотрим на разницу!

Сначала мы должны обновить нашу модель

class Model:ObservableObject {
    @Published var toggle = false
    var id: UUID {
        UUID()
    }
}

и следующий наш просмотр

FullWidthImageView().id(model.id)

Теперь все работает так, как мы ожидали. enter image description here

В другом примере, где "стандарт" «состояние / привязка просто не работают, проверьте SwiftUI иерархического выбора с динамическими c сбоями данных

ОБНОВЛЕНИЕ

В качестве временного обходного пути вы can mimi c Список по ScrollView

import SwiftUI

struct Row: View {
    let i:Int
    var body: some View {
        VStack {
            Image(systemName: "trash")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 200)
                .contextMenu(ContextMenu {
                    Button("A") {}
                    Button("B") {}
                })
            Text("I don’t want to show in preview because I don’t have context menu modifire").bold()
        }.padding()
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            ScrollView {
                ForEach(0 ..< 20) { (i) in
                    VStack {
                        Divider()
                        Row(i: i)
                    }
                }
            }
        }
    }
}

Это не оптимально, но в вашем случае это должно работать enter image description here enter image description here

...