【问题标题】:In swiftUI is it possible to add a new view onto the screen with a button?在 swiftUI 中是否可以使用按钮在屏幕上添加新视图?
【发布时间】:2023-03-07 05:55:01
【问题描述】:

每次点击按钮时,我都希望出现一个新的 cardView。我想知道这在 swiftUI 中是否可行,如果可以,我需要采取什么行动。如果我能够将一些参数传递给 cardView 结构会更好,但任何帮助都会很棒!


struct ContentView: View {
    var body: some View {
        ZStack {
            VStack {
                TextButton(action: {print("Button tapped")}, text: "new card")
                CardView()
            }
        }
    }
}

struct CardView: View {
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color(#colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)))
                .frame(width: 100, height: 100 * 1.618)
                .cornerRadius(16)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)

            VStack {
                Text("Card")
                    .font(.system(size: 10) )
                    .foregroundColor(.white)
                    .bold()
            }
        }
    }
}


struct TextButton: View {
    let action: () -> Void
    let text: String

    var body: some View {
        Button(action: action, label: {
            Text(text)
                .padding(.horizontal, 16)
                .padding(.vertical, 16)
                .foregroundColor(.white)
                .background(Color.blue)
                .cornerRadius(.infinity)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)
        })
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
} ```

【问题讨论】:

    标签: ios swift iphone swiftui


    【解决方案1】:

    在 SwiftUI 中,View 反映的是 State 数据,所以你不直接修改 View,而是修改 State 数据,基于 State 构建 View。这是 SwiftUI 背后的核心原则,它允许您将 View 关注点与驱动它的数据(在某些术语中为 ViewModel)分开。

    所以,假设我们有一个Card 的数据模型(使其符合Identifiable - 这将在以后需要):

    struct Card: Identifiable {
      let id = UUID()
      let name: String
    }
    

    让我们在你的视图中定义一个卡片数组作为状态变量:

    @State private var cards: [Card] = [Card(name: "foo")]
    

    然后主体可以使用ForEachList 视图显示这些卡片:

    var body = some View {
      VStack() {
        Button("Add Card") {
           self.cards.append(Card(name: "I'm an added card"))
        }
        ForEach(cards) { card in
           CardView(for: card) // if your CardView had parameters
        }
      }
    }
    

    发生的情况是按钮的闭包向cards 状态变量添加了一个新的Card 实例。就是这样。它不会直接更改视图中的任何内容。 View 看到变化(这就是 SwiftUI 在幕后所做的)并重新渲染自己。

    您需要Card 以符合Identifiable 的原因是让ForEach 知道如何唯一标识每张卡。在不符合可识别的情况下,您可以使用这样的关键路径:

    ForEach(cards, id: \.self) { card in
      // ...
    }
    

    【讨论】:

    • 非常感谢!您提供了非常清晰和连贯的解释。惊人的东西。问题解决了。
    【解决方案2】:

    看看这个:

    import SwiftUI
    
    struct ContentView: View {
    
        @State var cards: [CardView] = [CardView()]
    
    
    
        var body: some View {
            VStack {
                TextButton(action: {
                    print("Button tapped")
                    self.cards.append(CardView())
    
                }, text: "new card")
                ZStack {
                    ForEach(cards, id: \.self) { card in
                        card
                            .rotationEffect(card.angle)
    
                    }
    
                }
            }
        }
    }
    
    struct CardView: View, Hashable, Identifiable {
    
        var id = UUID()
    
        var angle : Angle {
            let angle = Angle(degrees: Double.random(in: 0...30))
            print(angle.degrees)
            return angle
        }
        var body: some View {
            ZStack {
                Rectangle()
                    .fill(Color(#colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)))
                    .frame(width: 100, height: 100 * 1.618)
                    .cornerRadius(16)
                    .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                    .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)
    
                VStack {
                    Text("Card \(angle.degrees)")
                        .font(.system(size: 10) )
                        .foregroundColor(.white)
                        .bold()
                }
            }
        }
    }
    
    
    struct TextButton: View {
        let action: () -> Void
        let text: String
    
        var body: some View {
            Button(action: action, label: {
                Text(text)
                    .padding(.horizontal, 16)
                    .padding(.vertical, 16)
                    .foregroundColor(.white)
                    .background(Color.blue)
                    .cornerRadius(.infinity)
                    .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.1), radius: 1, x: 0, y: 1)
                    .shadow(color: Color(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)).opacity(0.2), radius: 10, x: 0, y: 10)
            })
        }
    }
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-24
      • 2013-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-30
      相关资源
      最近更新 更多