使用列表而不是ScrollView的SwiftUI列表渲染问题

时间:2020-09-28 22:11:48

标签: swift macos swiftui appkit swiftui-list

我正在NSPopover中为以下UI使用SwiftUI:

enter image description here

正如人们所见,UI的行为不符合预期。

我使用以下SwiftUI代码:

struct PaletteListUIView: View {
    @EnvironmentObject var colorPaletteManager: ColorPaletteManager
    
    var body: some View {
        List {
            if(colorPaletteManager.colorPalettes.count > 0) {
                ForEach(Array(self.colorPaletteManager.colorPalettes.enumerated()), id: \.element.id) { idx, palette in
                    PaletteListRowUIView(
                        colorPalette: palette,
                        isSelected: self.colorPaletteManager.isSelected(index: idx),
                        onDelete: { self.colorPaletteManager.removeColorPalette(at: idx) },
                        onSelect: { self.colorPaletteManager.selectPalette(at: idx) },
                        onRename: {
                            self.colorPaletteManager.synchronize()
                    })
                }.frame(height: 50)
            } else {
                NoElementsUIView(heading: "You Have no Color Palettes", subheading: nil)
            }
            Button(action: {
                self.colorPaletteManager.addEmptyColorPalette()
            }) {
                Image("Plus")
            }.buttonStyle(PlainButtonStyle()).padding(10)
        }.frame(width: 256)
    }
}

extension NSTableView {
    open override func viewDidMoveToWindow() {
        super.viewDidMoveToWindow()
        
        backgroundColor = NSColor.clear
        enclosingScrollView!.drawsBackground = false
    }
}
struct PaletteListRowUIView: View {
    @State var colorPalette: ColorPalette
    var isSelected: Bool
    var onDelete: () -> Void
    var onSelect: () -> Void
    var onRename: () -> Void
    
    var body: some View {        
        return VStack(alignment: .leading) {
            HStack {
                Group {
                    if(isSelected) {
                        Ellipse().fill(Color.white)
                    } else {
                        Ellipse().stroke(Color.white)
                    }
                }.contentShape(Ellipse())
                .aspectRatio(1, contentMode: .fit).frame(width: 10, height: 10)
                .gesture(TapGesture().onEnded(onSelect))

                Text(colorPalette.name)

                VStack(alignment: .trailing) {
                    Button(action: onDelete) {
                        Image("Trash").resizable().scaledToFit().frame(width: 10, height: 10)
                    }.buttonStyle(PlainButtonStyle()).padding(10)
                }
            }
            if(self.colorPalette.colors.count > 0) {
                HStack(spacing: 0) {
                    ForEach(self.colorPalette.colors) { color in
                        Rectangle().fill(Color(color))
                    }
                }.mask(RoundedRectangle(cornerRadius: 10))
            } else {
                RoundedRectangle(cornerRadius: 10).stroke(Color.gray)
            }
        }
    }
}

使用ScrollView代替List时不会发生此问题。 显然,ListScrollView的区别非常大,因为我还需要更改此内容:

extension ColorPalette: Identifiable {
    public var id: String {
        return self.name
    }
}

...对此...

extension ColorPalette: Identifiable {
    public var id: UUID {
        return UUID()
    }
}

...否则,访问\.element.id(在第一个代码段的ForEach内)将导致Unexpectedly found nil while implicitly unwrapping an Optional value

我的posts中的另一个用户看到了SwiftUI List的很多问题。 可悲的是我仍然没有答案。我是在做根本上是错误的事情,还是SwiftUI仍然很不稳定?

0 个答案:

没有答案