ios 使用SwiftUI切换更改时的动画

u1ehiz5o  于 2023-05-30  发布在  iOS
关注(0)|答案(1)|浏览(230)

我正在构建一个简单的设置屏幕。
当第一个设置被激活时,速度控制出现。当它关闭时,速度控制消失。
根据我对SwiftUI的了解,这应该会根据下面的代码自动动画,但它只是出现和消失。
我如何使用SwiftUI使这个动画更好,使它从上面的单元格向下滑动,就像在53:00的this presentation中一样?

import SwiftUI
import Combine

struct ContentView : View {

    @ObjectBinding var settingsStore: SettingsStore

    var body: some View {
        NavigationView {
            Form {
                Toggle(isOn: $settingsStore.settingActivated.animation(.basic(duration: 3, curve: .easeInOut))) {
                    Text("Setting Activated")
                }
                if settingsStore.settingActivated {
                    VStack(alignment: .leading) {
                        Text("Speed Control")
                        HStack {
                            Image(systemName: "tortoise")
                            Slider(value: .constant(10), from: 0, through: 50, by: 1)
                            Image(systemName: "hare")
                        }
                    }.transition(.opacity)
                }
            }.navigationBarTitle(Text("Settings"))
        }
    }
}

class SettingsStore: BindableObject {

    let didChange = PassthroughSubject<Void, Never>()

    var settingActivated: Bool = UserDefaults.settingActivated {
        didSet {

            UserDefaults.settingActivated = settingActivated

            didChange.send()
        }
    }
}

extension UserDefaults {

    private struct Keys {
        static let settingActivated = "SettingActivated"
    }

    static var settingActivated: Bool {
        get {
            return UserDefaults.standard.bool(forKey: Keys.settingActivated)
        }
        set {
            UserDefaults.standard.set(newValue, forKey: Keys.settingActivated)
        }
    }
}
qij5mzcb

qij5mzcb1#

同样的bug也出现在iOS 15和iOS 16中。你现在可以使用属性@AppStorage来阅读和写入默认存储中的值,但是动画仍然不能使用它。

struct SettingsView: View {
    @AppStorage("SettingActivated") var settingActivated: Bool = false
    var body: some View {
        Form {
            Toggle(isOn: $settingActivated.animation(.basic(duration: 3, curve: .easeInOut))) {
                Text("Activate Setting")
            }
            if settingActivated {
                Text("Setting Activated")
            }
        }
    }
}

我发现了一个解决方法,它只需要很少的额外代码,然后工作正常。SwiftUI运行动画需要常用的@State属性,只要@AppStorage属性更改,就可以设置此属性(1):

struct SettingsView: View {
    @AppStorage("SettingActivated") var settingActivated: Bool = false
    @State private var settingShown: Bool = false
    var body: some View {
        Form {
            Toggle("Activate Setting", isOn: $settingActivated.animation())
                .onChange(of: value) { value in
                    withAnimation {settingShown = value}  // 1)
                }
            if settingShown {
                Text("Setting Activated")
            }
        }
        .onAppear() {
            settingShown = settingActivated  // 2)
        }
    }
}

但是,由于无法从@AppStorage初始化@State,因此需要在. onAppear中执行此操作。(二)
就是这样表单和列表中的动画,由@AppStorage切换触发。

相关问题