Ios 根据保存的状态自动在SwiftUI中激活动画
我正在尝试编写一个显示3个按钮的视图,但无法在加载时启动动画 点击按钮时,我希望它设置动画,直到:Ios 根据保存的状态自动在SwiftUI中激活动画,ios,swiftui,ios-animations,Ios,Swiftui,Ios Animations,我正在尝试编写一个显示3个按钮的视图,但无法在加载时启动动画 点击按钮时,我希望它设置动画,直到: 它被第二次点击 点击3个按钮中的另一个 我已经使用@Environment对象来存储运行状态,使代码正常工作。它可以在3个按钮之间切换: 代码如下: struct ContentView : View { @EnvironmentObject var model : ModelClockToggle var body: some View { VStack
struct ContentView : View {
@EnvironmentObject var model : ModelClockToggle
var body: some View {
VStack {
ForEach(0...2) { timerButton in
ActivityBreak(myId: timerButton)
.padding()
}
}
}
}
import SwiftUI
struct ActivityBreak : View {
var myId: Int
@EnvironmentObject var model : ModelClockToggle
let anim1 = Animation.basic(duration: 1.0, curve: .easeInOut).repeatCount(Int.max)
let noAni = Animation.basic(duration: 0.2, curve: .easeInOut).repeatCount(0)
var body: some View {
return Circle()
.foregroundColor(.red)
.scaleEffect(self.model.amIRunning(clock: self.myId) ? 1.0 : 0.6)
.animation( self.model.amIRunning(clock: self.myId) ? anim1 : noAni )
.tapAction {
self.model.toggle(clock: self.myId)
}
}
}
为完整起见,模型为:
import Foundation
import SwiftUI
import Combine
class ModelClockToggle: BindableObject {
let didChange = PassthroughSubject<ModelClockToggle, Never>()
private var clocksOn: [Bool] = [false,false,false]
init() {
clocksOn = []
clocksOn.append(UserDefaults.standard.bool(forKey: "toggle1"))
clocksOn.append(UserDefaults.standard.bool(forKey: "toggle2"))
clocksOn.append(UserDefaults.standard.bool(forKey: "toggle3"))
debugPrint(clocksOn)
}
func toggle(clock: Int) {
debugPrint(#function)
if clocksOn[clock] {
clocksOn[clock].toggle()
} else {
clocksOn = [false,false,false]
clocksOn[clock].toggle()
}
saveState()
didChange.send(self)
}
func amIRunning(clock: Int) -> Bool {
debugPrint(clocksOn)
return clocksOn[clock]
}
private func saveState() {
UserDefaults.standard.set(clocksOn[0], forKey: "toggle1")
UserDefaults.standard.set(clocksOn[1], forKey: "toggle2")
UserDefaults.standard.set(clocksOn[2], forKey: "toggle3")
}
}
<代码>导入基础
导入快捷键
进口联合收割机
类ModelClockToggle:BindableObject{
让didChange=PassthroughSubject()
私有变量clocksOn:[Bool]=[false,false,false]
init(){
clocksOn=[]
append(UserDefaults.standard.bool(forKey:“toggle1”))
append(UserDefaults.standard.bool(forKey:“toggle2”))
append(UserDefaults.standard.bool(forKey:“toggle3”))
调试打印(clocksOn)
}
功能切换(时钟:Int){
debugPrint(#函数)
如果是clocksOn[时钟]{
clocksOn[clock].toggle()
}否则{
clocksOn=[假,假,假]
clocksOn[clock].toggle()
}
saveState()
发送(自我)
}
func amIRunning(时钟:Int)->Bool{
调试打印(clocksOn)
返回时钟
}
私有func存储状态(){
UserDefaults.standard.set(clocksOn[0],forKey:“toggle1”)
UserDefaults.standard.set(clocksOn[1],forKey:“toggle2”)
UserDefaults.standard.set(clocksOn[2],forKey:“toggle3”)
}
}
如何根据传入视图的@Environment对象在加载时开始重复动画?现在SWIFTUI似乎只考虑视图加载后的状态变化。< /P>
我尝试添加一个.onAppear修改器,但这意味着我必须使用不同的动画师,这有非常奇怪的效果
感谢您的帮助。在您的示例中,您使用的是隐式动画。这些动画将查找任何可设置动画的参数的更改,如大小、位置、不透明度、颜色等。当SwiftUI检测到任何更改时,它将设置动画 在您的特定情况下,圆在未激活时通常缩放为0.6,在激活时缩放为1.0。在“非活动”和“活动”状态之间进行更改,使您的圆圈改变比例,这些更改将在循环中设置动画 但是,您的问题是,最初以1.0比例加载的圆(因为模型说它处于活动状态)将检测不到更改:它从1.0开始,保持在1.0。所以没有什么可以动画化的 在您的评论中,您提到了一个解决方案,该解决方案涉及让模型延迟加载圆状态的状态。这样,首先创建视图,然后要求模型加载状态,然后在视图中进行可以设置动画的更改。这是可行的,但是,这有一个问题 您正在使模型的行为依赖于视图。当它真的应该是相反的时候。假设屏幕上有两个视图实例。根据时间的不同,一个启动良好,但另一个不会 解决这个问题的方法是确保整个逻辑由视图本身处理。你想要完成的是,你的圆圈总是以0.6的比例创建。然后,检查模型以查看圆圈是否应处于活动状态。如果是,请立即将其更改为1.0。这样可以保证视图的动画效果 下面是一个可能的解决方案,它使用名为
booted
的@State
变量来跟踪此情况。您的圆将始终以0.6的比例创建,但一旦调用onAppear()方法,视图将缩放到1.0(如果活动),从而生成相应的动画
struct ActivityBreak:视图{
var myId:Int
@环境对象变量模型:ModelClockToggle
@已启动状态私有变量:Bool=false
//β4
让anim1=Animation.easeInOut(持续时间:1.0)。repeatCount(Int.max)
让noAni=Animation.easeInOut(持续时间:0.2)。repeatCount(0)
//贝塔3
//让anim1=Animation.basic(持续时间:1.0,曲线:.easeInOut)。repeatCount(Int.max)
//让noAni=Animation.basic(持续时间:0.2,曲线:.easeInOut)。repeatCount(0)
var body:一些观点{
返回圆()
.foregroundColor(.red)
.scaleEffect(!booted?0.6:self.model.amIRunning(时钟:self.myId)?1.0:0.6)
.animation(self.model.amIRunning(clock:self.myId)?anim1:noAni)
.tapAction{
self.model.toggle(时钟:self.myId)
}
奥纳佩尔先生{
self.booted=true
}
}
}
在您的示例中,您使用的是隐式动画。这些动画将查找任何可设置动画的参数的更改,如大小、位置、不透明度、颜色等。当SwiftUI检测到任何更改时,它将设置动画
在您的特定情况下,圆在未激活时通常缩放为0.6,在激活时缩放为1.0。在“非活动”和“活动”状态之间进行更改,使您的圆圈改变比例,这些更改将在循环中设置动画
但是,您的问题是,最初以1.0比例加载的圆(因为模型说它处于活动状态)将检测不到更改:它从1.0开始,保持在1.0。所以没有什么可以动画化的
在您的评论中,您提到了一个解决方案,该解决方案涉及让模型延迟加载圆状态的状态。这样,首先创建视图,然后要求模型加载状态,然后在视图中进行可以设置动画的更改。这是可行的,但是,这有一个问题
您正在使模型的行为依赖于视图。当它真的应该是相反的时候。