如何在 ZStack 中捕获自定义卡片视图上的点击?
How do I capture a tap on a custom card view in a ZStack?
我正在努力重新创建类似电子钱包视图的内容,但无法真正弄明白。我已经 hard-coded 偏移到我的 ZStack 中,但当然我也想避免这种情况。似乎偏移量使水龙头根本无法注册。到目前为止,这是我的代码,点击一张卡片应该会在白色和黄色之间更改其标题的颜色。
最后,当然,我想将动画添加到卡片堆中,并能够 "pull" 从其中添加一个动画以使其成为主要视图。但我必须先弄清楚如何抓住水龙头...
我以这个视频为基础,但它并没有达到我想要的程度:
https://nsscreencast.com/episodes/399-swiftui-transforms-and-animations
import SwiftUI
struct BetterCards: View {
var body: some View {
ScrollView (.vertical) {
ZStack {
CardView(title: "adidas", color: .blue, offset: 0.0)
CardView(title: "Le Crueset", color: .pink, offset: 90.0)
CardView(title: " Card", color: .black, offset: 180.0)
CardView(title: "Sandusk", color: .orange, offset: 270.0)
}
}
}
}
struct CardView: View {
@State var isYellow: Bool = false
let title: String
let color: Color
let offset: CGFloat
var body: some View {
Button(action: {
self.isYellow.toggle()
}) {
ZStack {
Rectangle()
.fill(color)
.cornerRadius(10)
.frame(width: 320, height: 210)
VStack {
Text(title)
.font(.largeTitle)
.bold()
.foregroundColor(isYellow ? .yellow : .white)
.padding()
Spacer()
}
}.shadow(radius: 2.0)
.offset(x: 0, y: offset)
}.onTapGesture {
print("Tapped: \(self.title)")
}
}
}
struct BetterCards_Previews: PreviewProvider {
static var previews: some View {
BetterCards()
}
}
struct ContentView: View {
var body: some View {
ScrollView (.vertical) {
ZStack(alignment: .top) {
CardView(title: "adidas", color: .blue, paddingOffset: 0)
CardView(title: "Le Crueset", color: .pink, paddingOffset: 90)
CardView(title: " Card", color: .black, paddingOffset: 180)
CardView(title: "Sandusk", color: .orange, paddingOffset: 270)
}
}
}
}
struct CardView: View {
@State var isYellow: Bool = false
let title: String
let color: Color
var paddingOffset: CGFloat
var body: some View {
ZStack {
Rectangle()
.fill(color)
VStack {
Text(title)
.font(.largeTitle)
.bold()
.foregroundColor(isYellow ? .yellow : .white)
.padding()
Spacer()
}
}.shadow(radius: 2.0)
.cornerRadius(10)
.frame(width: 320, height: 210)
.padding(.top, paddingOffset)
.onTapGesture {
self.isYellow.toggle()
print("Tapped: \(self.title)")
}
}
}
我认为您不需要在同一个视图中同时使用 Button
和 onTapGesture
。您的 CardView
已经是一个按钮,因此它将注册点击手势。为了使其正常工作,我建议您移动按钮本身的偏移量。也看起来只有当它有足够的高度时它才会在所有视图上注册点击,所以我在设置偏移量后在按钮上设置了一个框架。
总的来说,代码看起来像这样:
import SwiftUI
struct BetterCards: View {
var body: some View {
ScrollView (.vertical) {
ZStack(alignment: .top) {
CardView(title: "adidas", color: .blue, offset: 0.0)
CardView(title: "Le Crueset", color: .pink, offset: 90.0)
CardView(title: " Card", color: .black, offset: 180.0)
CardView(title: "Sandusk", color: .orange, offset: 270.0)
}
.padding()
}
}
}
struct CardView: View {
@State var isYellow: Bool = false
let title: String
let color: Color
let offset: CGFloat
var body: some View {
Button(action: {
self.isYellow.toggle()
print("Tapped: \(self.title)")
}) {
ZStack {
Rectangle()
.fill(color)
.cornerRadius(10)
.frame(width: 320, height: 210)
VStack {
Text(title)
.font(.largeTitle)
.bold()
.foregroundColor(isYellow ? .yellow : .white)
.padding()
Spacer()
}
.frame(width: 320, height: 210)
}
.shadow(radius: 2.0)
}
.offset(x: 0, y: offset)
.frame(width: 320, height: 210 + offset, alignment: .top)
}
}
您可以在不同的视图上调整对齐和填充以获得您需要的内容。
谢谢你们,Natalia 和 Mac3n
这让我开始思考,我最终使用了 VStack
很高兴听到任何评论。我不确定这是最好的方法。
我取消了偏移并在卡片视图中使用了两个框架 - 一个用于矩形,一个用于 ZStack。但是,我仍在尝试计算 VStack 上 .frame 的数学。好像是卡片数量+卡片实际高度的倍数,加上一些我无法确定的变量。
import SwiftUI
struct BetterCards: View {
let multiplier:CGFloat = 6
var body: some View {
ScrollView {
Text("HEADER").background(Color(.blue))
VStack {
CardView(title: " Card", color: .black)
CardView(title: "adidas", color: .blue)
CardView(title: "Puma", color: .green)
CardView(title: "Le Crueset", color: .yellow)
// CardView(title: "adidas", color: .blue)
// CardView(title: "OnlyLyon", color: .green)
// CardView(title: "Le Crueset", color: .yellow)
CardView(title: "adidas", color: .blue)
CardView(title: "Sandusk", color: .orange)
// CardView(title: "Le Crueset", color: .pink)
}
.frame(width: 400, height: multiplier * 60 + (430 - ( 52 )))
.padding()
.background(Color.gray)
Text("FOOTER").background(Color(.blue))
}
.background(Color.yellow)
}
}
struct CardView: View {
@State var isYellow: Bool = false
let title: String
let color: Color
var body: some View {
ZStack {
Rectangle()
.fill(color)
.cornerRadius(10)
.frame(width: 370, height: 430)
VStack {
Text(title)
.font(.largeTitle)
.bold()
.foregroundColor(isYellow ? .yellow : .white)
.padding()
Spacer()
}
}
.frame(width: 370, height: 60)
.onTapGesture {
self.isYellow.toggle()
print("Tapped: \(self.title)")
}
.shadow(radius: 2.0)
}
}
struct BetterCards_Previews: PreviewProvider {
static var previews: some View {
BetterCards()
}
}
我正在努力重新创建类似电子钱包视图的内容,但无法真正弄明白。我已经 hard-coded 偏移到我的 ZStack 中,但当然我也想避免这种情况。似乎偏移量使水龙头根本无法注册。到目前为止,这是我的代码,点击一张卡片应该会在白色和黄色之间更改其标题的颜色。
最后,当然,我想将动画添加到卡片堆中,并能够 "pull" 从其中添加一个动画以使其成为主要视图。但我必须先弄清楚如何抓住水龙头...
我以这个视频为基础,但它并没有达到我想要的程度:
https://nsscreencast.com/episodes/399-swiftui-transforms-and-animations
import SwiftUI
struct BetterCards: View {
var body: some View {
ScrollView (.vertical) {
ZStack {
CardView(title: "adidas", color: .blue, offset: 0.0)
CardView(title: "Le Crueset", color: .pink, offset: 90.0)
CardView(title: " Card", color: .black, offset: 180.0)
CardView(title: "Sandusk", color: .orange, offset: 270.0)
}
}
}
}
struct CardView: View {
@State var isYellow: Bool = false
let title: String
let color: Color
let offset: CGFloat
var body: some View {
Button(action: {
self.isYellow.toggle()
}) {
ZStack {
Rectangle()
.fill(color)
.cornerRadius(10)
.frame(width: 320, height: 210)
VStack {
Text(title)
.font(.largeTitle)
.bold()
.foregroundColor(isYellow ? .yellow : .white)
.padding()
Spacer()
}
}.shadow(radius: 2.0)
.offset(x: 0, y: offset)
}.onTapGesture {
print("Tapped: \(self.title)")
}
}
}
struct BetterCards_Previews: PreviewProvider {
static var previews: some View {
BetterCards()
}
}
struct ContentView: View {
var body: some View {
ScrollView (.vertical) {
ZStack(alignment: .top) {
CardView(title: "adidas", color: .blue, paddingOffset: 0)
CardView(title: "Le Crueset", color: .pink, paddingOffset: 90)
CardView(title: " Card", color: .black, paddingOffset: 180)
CardView(title: "Sandusk", color: .orange, paddingOffset: 270)
}
}
}
}
struct CardView: View {
@State var isYellow: Bool = false
let title: String
let color: Color
var paddingOffset: CGFloat
var body: some View {
ZStack {
Rectangle()
.fill(color)
VStack {
Text(title)
.font(.largeTitle)
.bold()
.foregroundColor(isYellow ? .yellow : .white)
.padding()
Spacer()
}
}.shadow(radius: 2.0)
.cornerRadius(10)
.frame(width: 320, height: 210)
.padding(.top, paddingOffset)
.onTapGesture {
self.isYellow.toggle()
print("Tapped: \(self.title)")
}
}
}
我认为您不需要在同一个视图中同时使用 Button
和 onTapGesture
。您的 CardView
已经是一个按钮,因此它将注册点击手势。为了使其正常工作,我建议您移动按钮本身的偏移量。也看起来只有当它有足够的高度时它才会在所有视图上注册点击,所以我在设置偏移量后在按钮上设置了一个框架。
总的来说,代码看起来像这样:
import SwiftUI
struct BetterCards: View {
var body: some View {
ScrollView (.vertical) {
ZStack(alignment: .top) {
CardView(title: "adidas", color: .blue, offset: 0.0)
CardView(title: "Le Crueset", color: .pink, offset: 90.0)
CardView(title: " Card", color: .black, offset: 180.0)
CardView(title: "Sandusk", color: .orange, offset: 270.0)
}
.padding()
}
}
}
struct CardView: View {
@State var isYellow: Bool = false
let title: String
let color: Color
let offset: CGFloat
var body: some View {
Button(action: {
self.isYellow.toggle()
print("Tapped: \(self.title)")
}) {
ZStack {
Rectangle()
.fill(color)
.cornerRadius(10)
.frame(width: 320, height: 210)
VStack {
Text(title)
.font(.largeTitle)
.bold()
.foregroundColor(isYellow ? .yellow : .white)
.padding()
Spacer()
}
.frame(width: 320, height: 210)
}
.shadow(radius: 2.0)
}
.offset(x: 0, y: offset)
.frame(width: 320, height: 210 + offset, alignment: .top)
}
}
您可以在不同的视图上调整对齐和填充以获得您需要的内容。
谢谢你们,Natalia 和 Mac3n
这让我开始思考,我最终使用了 VStack
很高兴听到任何评论。我不确定这是最好的方法。
我取消了偏移并在卡片视图中使用了两个框架 - 一个用于矩形,一个用于 ZStack。但是,我仍在尝试计算 VStack 上 .frame 的数学。好像是卡片数量+卡片实际高度的倍数,加上一些我无法确定的变量。
import SwiftUI
struct BetterCards: View {
let multiplier:CGFloat = 6
var body: some View {
ScrollView {
Text("HEADER").background(Color(.blue))
VStack {
CardView(title: " Card", color: .black)
CardView(title: "adidas", color: .blue)
CardView(title: "Puma", color: .green)
CardView(title: "Le Crueset", color: .yellow)
// CardView(title: "adidas", color: .blue)
// CardView(title: "OnlyLyon", color: .green)
// CardView(title: "Le Crueset", color: .yellow)
CardView(title: "adidas", color: .blue)
CardView(title: "Sandusk", color: .orange)
// CardView(title: "Le Crueset", color: .pink)
}
.frame(width: 400, height: multiplier * 60 + (430 - ( 52 )))
.padding()
.background(Color.gray)
Text("FOOTER").background(Color(.blue))
}
.background(Color.yellow)
}
}
struct CardView: View {
@State var isYellow: Bool = false
let title: String
let color: Color
var body: some View {
ZStack {
Rectangle()
.fill(color)
.cornerRadius(10)
.frame(width: 370, height: 430)
VStack {
Text(title)
.font(.largeTitle)
.bold()
.foregroundColor(isYellow ? .yellow : .white)
.padding()
Spacer()
}
}
.frame(width: 370, height: 60)
.onTapGesture {
self.isYellow.toggle()
print("Tapped: \(self.title)")
}
.shadow(radius: 2.0)
}
}
struct BetterCards_Previews: PreviewProvider {
static var previews: some View {
BetterCards()
}
}