在 swiftUI 中是不是可以使用按钮在屏幕上添加新视图?
Posted
技术标签:
【中文标题】在 swiftUI 中是不是可以使用按钮在屏幕上添加新视图?【英文标题】:In swiftUI is it possible to add a new view onto the screen with a button?在 swiftUI 中是否可以使用按钮在屏幕上添加新视图? 【发布时间】:2020-05-19 16:12:13 【问题描述】:每次点击按钮时,我都希望出现一个新的 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()
```
【问题讨论】:
【参考方案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")]
然后主体可以使用ForEach
或List
视图显示这些卡片:
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()
【讨论】:
以上是关于在 swiftUI 中是不是可以使用按钮在屏幕上添加新视图?的主要内容,如果未能解决你的问题,请参考以下文章