为什么SwiftUI上下文菜单在预览中显示所有行视图?

时间:2020-02-07 13:31:35

标签: ios swiftui contextmenu swiftui-list

列表行中有一个复杂的视图:

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修饰符的视图。 但是,当我长按图像时,我看不到预览中的唯一图像,而是所有行视图。

任何元素上都没有其他contextMenu。

如何在仅包含图像的上下文中进行预览?

UPD。 Here是说明问题的简单代码

2 个答案:

答案 0 :(得分:3)

这是一个有效的代码(模拟您的情况),即仅显示图像用于上下文菜单预览(已通过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)

            }
        }
    }
}

答案 1 :(得分:3)

直到您看到FullWidthImageView以及如何构造上下文菜单之前,我们都不知道为什么在您的情况下不起作用。 Asperi的答案是可行的示例,并且正确完成了! 但这真的可以解释您的麻烦吗?

麻烦的是,在仅将.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()
    }
}

在运行时,修改后的“上下文菜单”视图似乎是“静态的”

enter image description here

是的,长按后,您会看到垃圾桶图像,即使您关闭上下文视图时该图像已正确更新。 每按一次,您只会看到垃圾!

如何使其动态?我需要图像与“主视图! 在这里,我们有.id修饰符。让我们看看其中的区别!

首先我们必须更新模型

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

然后是我们的视图

FullWidthImageView().id(model.id)

现在它可以按我们预期的那样工作了。 enter image description here

再举一个例子,“标准”状态/绑定根本不起作用,请检查SwiftUI hierarchical Picker with dynamic data crashes

更新

作为临时解决方法,您可以通过ScrollView模仿List

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