我想在屏幕上有一个“徽章”,当条件满足时,它会从正常大小反弹到更大,然后反复恢复正常,直到不再满足条件。不过,我似乎无法让徽章停止“弹跳”。 一旦开始,势不可挡。
我试过的:
我尝试使用了一些动画,但它们可以分为使用“repeatForever”来达到预期效果的动画和不使用“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
}
}
}
最佳答案
我想到了!
使用 的动画.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 秒结束时完全停止。因此,我们通过线性动画将默认动画设置为停止动画。
关于SwiftUI:停止一个永远重复的动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59133826/