繁体   English   中英

在 Swift/SwiftUI 中包含多个视图类型的数组

[英]Array including multiple view types in Swift/SwiftUI

我想创建一个视图,人们可以在其中选择他们喜欢的背景图像,其中包括带有前景色的矩形或图像。 到目前为止,我已经通过创建这个来实现它

结构:

struct BackgroundImage : Identifiable{
var background : AnyView
let id = UUID()
}

我像这样将它们添加到数组中

视图模型:

class VM : ObservableObject{
    @Published var imageViews : Array<BackgroundImage> = Array<BackgroundImage>()
        
    init(){
        imageViews.append(BackgroundImage(background: AnyView(Rectangle().foregroundColor(Color.green))))
        imageViews.append(BackgroundImage(background: AnyView(Rectangle().foregroundColor(Color.yellow))))
        imageViews.append(BackgroundImage(background: AnyView(Image("Testimage"))))
    }

这允许我像这样循环遍历一组 BackgroundImages

看法:

LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())]) {
    ForEach(VM.imageViews, id: \.self.id) { view in
        ZStack{
            view.background
            //.resizable()
            //.aspectRatio(contentMode: .fill)
            .frame(width: g.size.width/2.25, height: g.size.height/8)                                                                                  
        .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
        }
    }
}

但是我无法添加

 .resizable()
 .aspectRatio(contentMode: .fill)

对于图像,因为 AnyView 不允许这样做。

有没有更好的方法来实现这一目标? 我应该只为形状/图像设置两个单独的 arrays 吗? 或者是否有更适合这个的替代 View 结构?

谢谢!

正如@DávidPásztor 在评论中提到的那样,将视图存储在 ViewModel 中是一个糟糕的设计。

实际上,您只需要存储颜色和图像名称即可。 让视图构建代码构建实际视图。

这是一个可能的实现。

struct BackgroundItem: Identifiable {
    private let uicolor: UIColor?
    private let imageName: String?
    let id = UUID()
    
    var isImage: Bool { imageName != nil }
    var color: UIColor { uicolor ?? .white }
    var name: String { imageName ?? "" }
    
    init(name: String? = nil, color: UIColor? = nil) {
        imageName = name
        uicolor = color
    }
}

class VM : ObservableObject{
    @Published var imageItems: [BackgroundItem] = []
        
    init() {
        imageItems = [.init(color: .green),
                      .init(color: .blue),
                      .init(name: "TestImage")]
    }
}

struct ContentView: View {
    @ObservedObject var vm = VM()

    var body: some View {
        GeometryReader { g in
            LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())]) {
                ForEach(vm.imageItems) { item in
                    ZStack{
                        if item.isImage {
                            Image(item.name)
                                .resizable()
                                .aspectRatio(contentMode: .fill)
                        } else {
                            Color(item.color)
                        }
                    }
                    .frame(width: g.size.width/2.25, height: g.size.height/8)
                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous)
                }
            }
        }
    }
}

注意:我想过使用enum来存储 imageName 和颜色之间的区别,但最简单的方法是只使用可选值并存储我需要的那个。 通过向视图构建代码公开的接口,您可以轻松地将实现更改为您希望存储信息的方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM