我想在屏幕上显示各种“徽章”,当满足条件时,它将从正常大小反弹到更大,然后反复回到正常状态,直到不再满足条件为止。但是,我似乎无法让徽章停止“弹跳”。一旦启动,便无法阻止。
我尝试过的事情: 我尝试使用一些动画,但是可以将它们归类为使用“ repeatForever”实现所需效果的动画,而不是不使用它们的动画。例如:
Animation.default.repeatForever(autoreverses: true)
和
Animation.spring(response: 1, dampingFraction: 0, blendDuration: 1)
(将阻尼设置为0可以永远消失)
其后是将其替换为.animation(nil)。似乎不起作用。有人有什么想法吗?提前非常感谢您!这是重现它的代码:
struct theProblem: View {
@State var active: Bool = false
var body: some View {
Circle()
.scaleEffect( active ? 1.08: 1)
.animation( active ? Animation.default.repeatForever(autoreverses: true): nil )
.frame(width: 100, height: 100)
.onTapGesture {
self.active = !self.active
}
}
}
答案 0 :(得分:3)
我知道了!
使用 .repeatForever()
的动画,如果您将动画替换为 nil
,则不会停止。 如果您将其替换为相同的动画但没有 .repeatForever()
,它将停止。 (或者,也可以使用其他任何会停止的动画,因此您可以使用持续时间为0的线性动画来立即停止)
换句话说,这将不起作用:.animation(active ? Animation.default.repeatForever() : nil)
但这确实可行:.animation(active ? Animation.default.repeatForever() : Animation.default)
为了使它更具可读性和易用性,我将其放入了扩展名中,您可以像这样使用它: .animation(Animation.default.repeat(while: active))
这是一个使用我的扩展程序的交互式示例,您可以将其与实时预览一起使用来进行测试:
import SwiftUI
extension Animation {
func `repeat`(while expression: Bool, autoreverses: Bool = true) -> Animation {
if expression {
return self.repeatForever(autoreverses: autoreverses)
} else {
return self
}
}
}
struct TheSolution: View {
@State var active: Bool = false
var body: some View {
Circle()
.scaleEffect( active ? 1.08: 1)
.animation(Animation.default.repeat(while: active))
.frame(width: 100, height: 100)
.onTapGesture {
self.active.toggle()
}
}
}
struct TheSolution_Previews: PreviewProvider {
static var previews: some View {
TheSolution()
}
}
据我所知,一旦分配了动画,它就永远不会消失,直到您的View完全停止。因此,如果您将.default动画设置为永久重复并自动倒转,然后分配了一个持续时间为4的线性动画,您会注意到默认的重复动画仍在继续,但直到它移动的速度越来越慢在4秒结束时完全停止。因此,我们通过线性动画将默认动画设置为停止动画。
答案 1 :(得分:0)
您的代码没有错,所以我认为这是苹果的缺陷。似乎有很多隐式动画(至少在Xcode 11.2中)。无论如何...
我建议考虑以下提供预期行为的替代方法。
struct TestAnimationDeactivate: View {
@State var active: Bool = false
var body: some View {
VStack {
if active {
BlinkBadge()
} else {
Badge()
}
}
.frame(width: 100, height: 100)
.onTapGesture {
self.active.toggle()
}
}
}
struct Badge: View {
var body: some View {
Circle()
}
}
struct BlinkBadge: View {
@State private var animating = false
var body: some View {
Circle()
.scaleEffect(animating ? 1.08: 1)
.animation(Animation.default.repeatForever(autoreverses: true))
.onAppear {
self.animating = true
}
}
}
struct TestAnimationDeactivate_Previews: PreviewProvider {
static var previews: some View {
TestAnimationDeactivate()
}
}