我在按钮标签内放置了以下视图:
struct ButtonLoading: View {
@Binding var isAnimating: Bool
var body: some View {
HStack(spacing: 4) {
CircleView(isAnimating: $isAnimating, idx: 0)
CircleView(isAnimating: $isAnimating, idx: 1)
CircleView(isAnimating: $isAnimating, idx: 2)
}
}
}
struct CircleView: View {
@Binding var isAnimating: Bool
var idx: Int
var body: some View {
Circle()
.fill(Color.white)
.frame(width: 4, height: 4)
.offset(y: isAnimating ? -4 : 0)
.animation(Animation.spring(response: 0.6, dampingFraction: 1.0, blendDuration: 1.0)
.repeatForever(autoreverses: true)
.delay(Double(idx) * 0.25))
}
}
那么以下意见:
struct ContentView: View {
@State var current: String = "one"
var body: some View {
ZStack {
Color.red.opacity(0.05).ignoresSafeArea()
VStack {
if current == "one" {
ViewOne()
.transition(.move(edge: .leading))
}
if current == "two" {
ViewTwo()
.transition(.move(edge: .trailing))
}
}
}
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation {
self.current = "two"
}
}
}
}
}
struct ViewOne: View {
var body: some View {
ZStack {
Color.blue.ignoresSafeArea()
Text("View One")
.foregroundColor(.white)
}
}
}
struct ViewTwo: View {
@State var isAnimating = false
var body: some View {
ZStack {
Color.white.ignoresSafeArea()
Button(action: {
isAnimating = true
}) {
ZStack(alignment: .center) {
ButtonLoading(isAnimating: $isAnimating)
.opacity(isAnimating ? 1 : 0)
Text("Continue")
.foregroundColor(.white)
.opacity(isAnimating ? 0 : 1)
}
.frame(height: 44)
.padding(.horizontal, 20)
.background(Color.blue)
}
}
}
}
当我单击按钮时,预期的行为是看到按钮的内容更改为省略号加载动画(点反复上下移动)。如果我删除.transition(.move(edge: .trailing))
附加到ViewTwo
. 但是,在其当前状态下,过渡动画似乎破坏了按钮动画。我看到它从后缘进进出出。有任何想法吗?SwiftUI 快把我逼疯了!
更新:
从一年前找到另一个答案,多产的 Asperi 做出了贡献。将我的按钮包装在其中一个中确实可以解决问题:
struct HelperView<Content: View> : UIViewControllerRepresentable {
var content: () -> Content
func makeUIViewController(context: Context) -> UIHostingController<Content> {
UIHostingController(rootView: content())
}
func updateUIViewController(_ host: UIHostingController<Content>, context: Context) {
host.rootView = content() // Update content
}
}
这是解决这个问题的唯一方法吗?
更新 2
切换到不透明度而不是偏移并添加一个.animation(nil)
解决了动画继承父过渡的问题:
struct CircleView: View {
@Binding var isAnimating: Bool
var idx: Int
var body: some View {
Circle()
.fill(Color.white)
.frame(width: 4, height: 4)
.animation(nil)
.opacity(isAnimating: 0 : 1)
.animation(Animation.spring(response: 0.6, dampingFraction: 1.0, blendDuration: 1.0)
.repeatForever(autoreverses: true)
.delay(Double(idx) * 0.25))
}
}
但是,添加自定义GeometryEffect
来更改偏移量不起作用。此外,添加.transition(.identity)
有和没有.animation(nil)
也不起作用。在这里尝试一切。=)