Warm tip: This article is reproduced from serverfault.com, please click

button-迅捷的用户界面

(button - Swift UI)

发布于 2020-11-28 15:20:06

我正在尝试解决以下问题。

我有一个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)")
          })
}

我想使此Text动画,但是,如果我直接向Text添加动画,则每个文本都会在点击的位置移动,而我只想为要单击的动画设置动画。

我想使文本进入Button视图并将其传递到主按钮的标签中,但显然嵌入按钮是一种可处以死刑的罪行。

有人有什么想法吗?提前致谢!

Questioner
lulubasher
Viewed
11
Nikolai 2020-12-01 01:58:22

我认为两种解决方案都是可行的。请在下面查看我的工作示例。

你想在单击按钮后继续应用效果吗?在这种情况下,我建议创建一个存储状态的自定义视图。

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()
    }
}