在
Button
内的 HStack
内使用多个 List
时,我有一个奇怪的动画行为。首先,我发现我需要使用 .automatic
以外的某些按钮样式才能使两个按钮在单行中正常工作。 这似乎效果很好,直到我想向这些按钮添加动画。我想在行的每一侧创建两个按钮,但仅当满足条件时才会显示第二个按钮,这可以通过单击第一个按钮来实现。简单的例子解释看起来像这样:
struct TestView: View {
@State
private var flag1 = true
@State
private var flag2 = false
var body: some View {
NavigationStack {
List {
HStack {
Button {
withAnimation {
flag1.toggle()
}
} label: {
Image(systemName: flag1 ? "checkmark.circle" : "circle")
}
Text("Some text")
if flag1 {
Spacer()
Button {
withAnimation {
flag2.toggle()
}
} label: {
Image(systemName: flag2 ? "checkmark.circle" : "circle")
}
}
}
.buttonStyle(.borderless)
}
}
}
}
上面的代码会导致这种奇怪的动画行为:
当我删除按钮样式修改器(
.buttonStyle(.borderless)
)时,动画效果更好,但仍然不理想。当第二个按钮应该隐藏时,有用于过渡的动画,但有时会出现动画,有时则没有动画。最重要的是,在这种情况下,两个按钮操作会同时触发:
我发现的最佳解决方案是将按钮替换为
.onTapGesture
修饰符:
struct TestView: View {
@State
private var flag1 = true
@State
private var flag2 = false
var body: some View {
NavigationStack {
List {
HStack {
Image(systemName: flag1 ? "checkmark.circle" : "circle")
.onTapGesture {
withAnimation {
flag1.toggle()
}
}
Text("Some text")
if flag1 {
Spacer()
Image(systemName: flag2 ? "checkmark.circle" : "circle")
.onTapGesture {
withAnimation {
flag2.toggle()
}
}
}
}
}
}
}
}
然而,使用我在按钮格式和第二个按钮出现的动画上松散的内容仍然是随机的。所以,这是我的问题:
Button
行上放置 2 个 List
而不会出现动画问题?.buttonStyle(.borderless)
或使用 .onTapGesture
时?.onTapGesture
而不是 Button
会失去很多吗?如何以看起来像(并保持这种方式)正常 Button
的方式格式化组件?In regards to inconsistencies in animation behavior, consider explicitly specifying the transition for the second button's appearance?
In regards to button and onTap... onTapGesture is more flexible but you will have to manage animations and state changes manually.
Just to be clear.. when you click into the "Some text" circle you want the second button to appear visible and with the checkmark indicator?
I achieved the above description by using a Timer to control the appearance of a checkmark inside the second button after a delay, allowing for more control over the animation. I tested the solution below on an actual device (not the simulator), and it seems to be working as expected.
import SwiftUI
struct TestView: View {
@State private var flag1 = true
@State private var flag2 = false
var body: some View {
NavigationStack {
List {
HStack {
Image(systemName: flag1 ? "checkmark.circle" : "circle")
.onTapGesture {
withAnimation {
flag1.toggle()
// Toggle flg2 after 5 second delay
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
withAnimation {
flag2 = true // Set flg 2 to true
}
}
}
}
Text("Some text")
if flag1 {
Spacer()
Image(systemName: flag2 ? "checkmark.circle" : "circle")
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
...