SwiftUI: Можете ли вы анимировать изменение самих данных, а не только реакцию представления на изменение? - PullRequest
0 голосов
/ 02 августа 2020

Можно ли просто анимировать изменение от значения a к значению b свойства, а не просто анимировать реакцию представления на изменение свойства?

Например, представьте, что вы нажимаете кнопку, которая увеличивает свойство на 10, хотя вместо немедленного изменения приложение будет обновлять свойство в соответствии с временной кривой каждый раз, когда представление визуализируется на протяжении анимации.

struct ExampleView: View {
    
    @State private var exampleNumber: Double = 0.0 {
        didSet {
            print("New value is \(exampleNumber)")
        }
    }
    
    var body: some View {
        
        VStack {
            Text("Number: \(exampleNumber)")
            
            Button(action: {
                withAnimation(.easeInOut) {
                    exampleNumber += 10.0
                }
            }, label: {
                Text("Smoothly add 10")
            })
        }
    }
}

Чтобы было ясно, это значение исходного свойства, которое я хочу оживить, а не только значение, отображаемое в представлении. Так, например, на устройстве с частотой 60 кадров в секунду метод печати «Новое значение ...» будет выполняться 60 раз в секунду при печати нового значения, которое соответствует временной кривой .easeInOut.

Это кажется возможным с Animatable или родственники, но я пока не могу заставить его работать. Заранее благодарю за помощь!

1 Ответ

0 голосов
/ 02 августа 2020

Вот демонстрация возможного подхода. Протестировано с Xcode 12 / iOS 14

демо

struct DemoAnimatingNumber: View {
    @State private var number = Double.zero

    var body: some View {
        Rectangle().fill(Color.yellow)
            .frame(maxWidth: .infinity, maxHeight: 60)
            .modifier(AnimatingNumber(number: number))
            .animation(Animation.easeInOut(duration: 2), value: number)
            .onTapGesture {
                number = number == Double.zero ? 10 : Double.zero
            }
    }
}

struct AnimatingNumber: AnimatableModifier {
    var number: Double

    var animatableData: Double {
        get { number }
        set { number = newValue }
    }

    func body(content: Content) -> some View {
        content.overlay(
            Text("Number: \(number, specifier: "%.1f")")
                .foregroundColor(.blue)
        )
    }
}
...