SwiftUI 自定义视图接受带有 ID 的视图?

Posted

技术标签:

【中文标题】SwiftUI 自定义视图接受带有 ID 的视图?【英文标题】:SwiftUI Custom View accepts a view with an ID? 【发布时间】:2021-02-03 22:35:15 【问题描述】:

我很可能忽略了一个简单的答案,但我似乎被困在如何做到这一点上。我尝试了很多东西,但我觉得有一个更简单的解决方案。

代码外观示例...

struct CustomView<Content: View>: View 
    var content: Content
    
    init(content: @escaping () -> Content) 
        self.content = content()
    
    
    var body: some View 
        
        ZStack 
         
            GeometryReader  geometry in

                let quadrant = geometry.size.height * 0.5
                
                VStack(spacing: 0) 
                    
                    HStack(spacing: 0) 
                        
                         // content.id(1)
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(Color.blue)
                            .cornerRadius(20)
                            .padding(10)
                            .frame(width: quadrant, height: quadrant)
                        
                         // content.id(2)
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(Color.blue)
                            .cornerRadius(20)
                            .padding(10)
                            .frame(width: quadrant, height: quadrant)
                            
                    
                    
                    
                    HStack(spacing: 0) 
                         // content.id(3)
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(Color.blue)
                            .cornerRadius(20)
                            .padding(10)
                            .frame(width: quadrant, height: quadrant)
                        
                        // content.id(4)
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(Color.blue)
                            .cornerRadius(20)
                            .padding(10)
                            .frame(width: quadrant, height: quadrant)
                    
                
                .background(Color.gray)
                .cornerRadius(10)
            
        .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width)
    


struct ExampleView: View 
    
    var body: some View 
        
        CustomView 
            
//            Text("Item 1").id(1)
           
//            Text("Item 2").id(2)

//            Text("Item 3").id(3)

//            Text("Item 4").id(4)
            
        
    


我想到了诸如使用 AnyView 数组作为属性之类的事情,并尝试制作一个扩展视图函数,将视图本身附加到数组中,但所有这些都让我更加困惑。

它的样子:

Picture

【问题讨论】:

【参考方案1】:

如果您查看ViewBuilder documentation,您会发现Apple 的设置是每个接受的Views 最多有10 个函数/初始化程序。

如果我要这样做,我会使用相同的模式(参见下面的CustomGridView2)。但是,如果您将在您的示例中传递相同的 View Text,那么仅传递数据会更好、更安全。

struct CustomGridView1: View 
    var items: [String]
    var columns: [GridItem] =
        Array(repeating: .init(.flexible()), count: 2)
    
    var body: some View 
        ZStack 
            LazyVGrid(columns: columns) 
                ForEach(items.indices, id: \.self) idx in
                    Rectangle()
                        .foregroundColor(.blue)
                        .overlay(
                            Text(items[idx]).id(idx)
                        )
                        .background(Color.blue)
                        .cornerRadius(20)
                        .padding(10)
                        .aspectRatio(1, contentMode: .fill)
                
            
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width)
            .background(Color.gray)
            .cornerRadius(10)
            
        
    

struct CustomGridView2<Content: View>: View 
    let content1: Content
    let content2: Content?
    let content3: Content?
    let content4: Content?
    var columns: [GridItem] =
        Array(repeating: .init(.flexible()), count: 2)
    
    init(@ViewBuilder _ content1: @escaping () -> Content) 
        self.content1 = content1()
        self.content2 = nil
        self.content3 = nil
        self.content4 = nil
    
    init(@ViewBuilder _ content1: @escaping () -> Content, _ content2: @escaping () -> Content) 
        self.content1 = content1()
        self.content2 = content2()
        self.content3 = nil
        self.content4 = nil
    
    init(@ViewBuilder _ content1: @escaping () -> Content, _ content2: @escaping () -> Content, _ content3: @escaping () -> Content) 
        self.content1 = content1()
        self.content2 = content2()
        self.content3 = content3()
        self.content4 = nil
    
    init(@ViewBuilder _ content1: @escaping () -> Content, _ content2: @escaping () -> Content, _ content3: @escaping () -> Content, _ content4: @escaping () -> Content) 
        self.content1 = content1()
        self.content2 = content2()
        self.content3 = content3()
        self.content4 = content4()
    
    var body: some View 
        ZStack 
            LazyVGrid(columns: columns) 
                
                content1
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(Color.blue)
                    .cornerRadius(20)
                    .padding(10)
                    .aspectRatio(1, contentMode: .fill)
                
                if content2 != nil
                    
                    content2
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(Color.blue)
                        .cornerRadius(20)
                        .padding(10)
                        .aspectRatio(1, contentMode: .fill)
                
                if content3 != nil
                    
                    content3
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(Color.blue)
                        .cornerRadius(20)
                        .padding(10)
                        .aspectRatio(1, contentMode: .fill)
                
                if content4 != nil
                    
                    content4
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(Color.blue)
                        .cornerRadius(20)
                        .padding(10)
                        .aspectRatio(1, contentMode: .fill)
                
            
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width)
            .background(Color.gray)
            .cornerRadius(10)
        
    

struct ExampleView2: View 
    var body: some View 
        CustomGridView2 
            Text("Item 1").id(1)
            Text("Item 2").id(2)
            Text("Item 3").id(3)
            Text("Item 4").id(4)
        
    

struct ExampleView1: View 
    var body: some View 
        CustomGridView1(items: ["Item 1", "Item 2", "Item 3", "Item 4"])
    

【讨论】:

哇,这两个都很棒。非常感谢! 如果这对你有用,你能接受我上面的回答吗?点赞也不错。 @loremipsum 只有拥有 15 名以上代表的用户才能为帖子投票。

以上是关于SwiftUI 自定义视图接受带有 ID 的视图?的主要内容,如果未能解决你的问题,请参考以下文章

在 SwiftUI 的自定义视图中访问图像的修饰符

SwiftUI 自定义对齐方式推动视图比父视图更宽

如何创建一个带有可选辅助 View 参数的 SwiftUI 视图?

带有列表的 SwiftUI 自定义导航栏

如何在 SwiftUI 中添加自定义容器视图

为啥自定义 SwiftUI 视图不响应状态变化