อาร์เรย์รวมถึงมุมมองหลายประเภทใน 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 ไม่อนุญาตให้ทำเช่นนี้
มีวิธีที่ดีกว่าในการบรรลุสิ่งนี้หรือไม่? ฉันควรมีอาร์เรย์แยกกันสองอาร์เรย์สำหรับรูปร่าง / รูปภาพแทนหรือไม่? หรือมีโครงสร้างมุมมองอื่นที่จะเหมาะกว่านี้หรือไม่?
ขอบคุณ!
คำตอบ
ดังที่ @ DávidPásztorกล่าวไว้ในความคิดเห็นการจัดเก็บ Views ใน 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 และสี แต่มันง่ายที่สุดที่จะใช้ตัวเลือกและจัดเก็บสิ่งที่ฉันต้องการ ด้วยอินเทอร์เฟซที่สัมผัสกับรหัสการสร้างมุมมองคุณสามารถเปลี่ยนการใช้งานได้อย่างง่ายดายตามที่คุณต้องการจัดเก็บข้อมูล