Swift UI - 为网格堆栈中的单个视图设置动画
Swift UI - Animating individual views in a gridstack
我正在尝试解决以下问题。
我有一个生成视图数组的 GridStack 视图。见下文:
struct GridStack<Content: View> : View {
let rows :Int
let columns : Int
let content : (Int, Int) -> Content
var body: some View {
VStack{
ForEach(0 ..< rows){ row in
HStack{
ForEach(0 ..< columns){ column in
self.content(row, column)
}
}
}
}
}
}
我目前有这个工作代码,它将数组的值发送到我的主代码中的整数变量 'upTo':
GridStack(rows: 3, columns: 4){ rows, cols in
Button(action: {
upTo = rows * 4 + cols + 1
}, label: {
Text("Number \(rows * 4 + cols + 1)")
})
}
我想使此文本具有动画效果,但是如果我直接向文本添加动画,则每一个文本都会在我想要 仅 想要设置动画的地方移动我正在点击。
我曾尝试将文本制作成按钮视图并将其传递到主按钮的标签中,但显然嵌入按钮是一种可判处死刑的犯罪行为。
有人有什么想法吗?
提前致谢!
我认为有两种方案可行。请参阅下面我的工作示例。
您希望应用的效果在单击按钮后持续存在吗?在这种情况下,我建议创建一个存储状态的自定义视图。
struct GridStack<Content: View> : View {
let rows :Int
let columns : Int
let content : (Int, Int) -> Content
var body: some View {
VStack{
ForEach(0 ..< rows){ row in
HStack{
ForEach(0 ..< columns){ column in
self.content(row, column)
}
}
}
}
}
}
struct MyCustomView: View {
let upTo: Int
let callback: () -> Void
@State var animate = false
var body: some View {
Button(action: {
self.callback()
self.animate.toggle()
}) {
Text("Number \(self.upTo)")
.background(self.animate ? Color.red : Color.white)
.animation(.linear(duration: 1.0))
}
}
}
struct ContentView2: View {
@State var upTo: Int = 0
var body: some View {
VStack {
Text("\(self.upTo)")
GridStack(rows: 3, columns: 4) { rows, cols in
MyCustomView(upTo: rows * 4 + cols + 1, callback: {
self.upTo = rows * 4 + cols + 1
})
}
}
}
}
struct ContentView2_Previews: PreviewProvider {
static var previews: some View {
ContentView2()
}
}
否则自定义按钮样式即可。在这种情况下,您可以访问配置的 isPressed
属性.
struct GridStack<Content: View> : View {
let rows :Int
let columns : Int
let content : (Int, Int) -> Content
var body: some View {
VStack{
ForEach(0 ..< rows){ row in
HStack{
ForEach(0 ..< columns){ column in
self.content(row, column)
}
}
}
}
}
}
struct MyCustomButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.background(configuration.isPressed ? Color.red : Color.white)
.animation(.linear(duration: 1.0))
}
}
struct ContentView2: View {
@State var upTo: Int = 0
var body: some View {
VStack {
Text("\(self.upTo)")
GridStack(rows: 3, columns: 4) { rows, cols in
Button(action: {
self.upTo = rows * 4 + cols + 1
}) {
Text("Number \(rows * 4 + cols + 1)")
}
.buttonStyle(MyCustomButtonStyle())
}
}
}
}
struct ContentView2_Previews: PreviewProvider {
static var previews: some View {
ContentView2()
}
}
我正在尝试解决以下问题。
我有一个生成视图数组的 GridStack 视图。见下文:
struct GridStack<Content: View> : View {
let rows :Int
let columns : Int
let content : (Int, Int) -> Content
var body: some View {
VStack{
ForEach(0 ..< rows){ row in
HStack{
ForEach(0 ..< columns){ column in
self.content(row, column)
}
}
}
}
}
}
我目前有这个工作代码,它将数组的值发送到我的主代码中的整数变量 'upTo':
GridStack(rows: 3, columns: 4){ rows, cols in
Button(action: {
upTo = rows * 4 + cols + 1
}, label: {
Text("Number \(rows * 4 + cols + 1)")
})
}
我想使此文本具有动画效果,但是如果我直接向文本添加动画,则每一个文本都会在我想要 仅 想要设置动画的地方移动我正在点击。
我曾尝试将文本制作成按钮视图并将其传递到主按钮的标签中,但显然嵌入按钮是一种可判处死刑的犯罪行为。
有人有什么想法吗? 提前致谢!
我认为有两种方案可行。请参阅下面我的工作示例。
您希望应用的效果在单击按钮后持续存在吗?在这种情况下,我建议创建一个存储状态的自定义视图。
struct GridStack<Content: View> : View {
let rows :Int
let columns : Int
let content : (Int, Int) -> Content
var body: some View {
VStack{
ForEach(0 ..< rows){ row in
HStack{
ForEach(0 ..< columns){ column in
self.content(row, column)
}
}
}
}
}
}
struct MyCustomView: View {
let upTo: Int
let callback: () -> Void
@State var animate = false
var body: some View {
Button(action: {
self.callback()
self.animate.toggle()
}) {
Text("Number \(self.upTo)")
.background(self.animate ? Color.red : Color.white)
.animation(.linear(duration: 1.0))
}
}
}
struct ContentView2: View {
@State var upTo: Int = 0
var body: some View {
VStack {
Text("\(self.upTo)")
GridStack(rows: 3, columns: 4) { rows, cols in
MyCustomView(upTo: rows * 4 + cols + 1, callback: {
self.upTo = rows * 4 + cols + 1
})
}
}
}
}
struct ContentView2_Previews: PreviewProvider {
static var previews: some View {
ContentView2()
}
}
否则自定义按钮样式即可。在这种情况下,您可以访问配置的 isPressed
属性.
struct GridStack<Content: View> : View {
let rows :Int
let columns : Int
let content : (Int, Int) -> Content
var body: some View {
VStack{
ForEach(0 ..< rows){ row in
HStack{
ForEach(0 ..< columns){ column in
self.content(row, column)
}
}
}
}
}
}
struct MyCustomButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.background(configuration.isPressed ? Color.red : Color.white)
.animation(.linear(duration: 1.0))
}
}
struct ContentView2: View {
@State var upTo: Int = 0
var body: some View {
VStack {
Text("\(self.upTo)")
GridStack(rows: 3, columns: 4) { rows, cols in
Button(action: {
self.upTo = rows * 4 + cols + 1
}) {
Text("Number \(rows * 4 + cols + 1)")
}
.buttonStyle(MyCustomButtonStyle())
}
}
}
}
struct ContentView2_Previews: PreviewProvider {
static var previews: some View {
ContentView2()
}
}