The*_*Fox 13 xcode swift swiftui
我想在屏幕上有一个“徽章”,当条件满足时,它会从正常大小反弹到更大,然后反复恢复正常,直到不再满足条件。不过,我似乎无法让徽章停止“弹跳”。一旦开始,势不可挡。
我尝试过的: 我尝试过使用一些动画,但它们可以分为使用“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
        }
    }
}
The*_*Fox 41
我想到了!
 .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()
    }
}
据我所知,一旦您分配动画,它永远不会消失,直到您的视图完全停止。因此,如果您将 .default 动画设置为永远重复并自动反转,然后您分配了一个持续时间为 4 的线性动画,您会注意到默认的重复动画仍在进行,但它的运动变得越来越慢,直到它在我们的 4 秒结束时完全停止。因此,我们通过线性动画将默认动画设置为停止动画。
小智 6
在经历了很多事情之后,我发现了一些对我有用的东西。至少暂时如此,直到我有时间找出更好的方法为止。
struct WiggleAnimation<Content: View>: View {
    var content: Content
    @Binding var animate: Bool
    @State private var wave = true
    var body: some View {
        ZStack {
            content
            if animate {
                Image(systemName: "minus.circle.fill")
                    .foregroundColor(Color(.systemGray))
                    .offset(x: -25, y: -25)
            }
        }
        .id(animate) //THIS IS THE MAGIC
        .onChange(of: animate) { newValue in
            if newValue {
                let baseAnimation = Animation.linear(duration: 0.15)
                withAnimation(baseAnimation.repeatForever(autoreverses: true)) {
                    wave.toggle()
                }
            }
        }
        .rotationEffect(.degrees(animate ? (wave ? 2.5 : -2.5) : 0.0),
                        anchor: .center)
    }
    init(animate: Binding<Bool>,
         @ViewBuilder content: @escaping () -> Content) {
        self.content = content()
        self._animate = animate
    }
}
使用
@State private var editMode = false
WiggleAnimation(animate: $editMode) {
    VStack {
        Image(systemName: image)
            .resizable()
            .frame(width: UIScreen.screenWidth * 0.1,
                   height: UIScreen.screenWidth * 0.1)
            .padding()
            .foregroundColor(.white)
            .background(.gray)
        
        Text(text)
            .multilineTextAlignment(.center)
            .font(KMFont.tiny)
            .foregroundColor(.black)
    }
}
它是如何工作的?这里的 .id(animate) 修饰符不会刷新视图,只是将其替换为新视图,因此它回到了原始状态。
同样,这可能不是最好的解决方案,但它适用于我的情况。
使用交易怎么样
在下面的代码中,我根据动画的状态关闭或打开动画active
警告:一定要使用withAnimation,否则什么都不起作用
@State var active: Bool = false
var body: some View {
    Circle()
        .scaleEffect(active ? 1.08: 1)
        .animation(Animation.default.repeatForever(autoreverses: true), value: active)
        .frame(width: 100, height: 100)
        .onTapGesture {
            useTransaction()
        }
}
func useTransaction() {
    var transaction = Transaction()
    transaction.disablesAnimations = active ? true : false
    
    withTransaction(transaction) {
        withAnimation {
            active.toggle()
        }
    }
}
| 归档时间: | 
 | 
| 查看次数: | 3886 次 | 
| 最近记录: |