'swiftui, animation applied to parent effect child animation(Part II)

PREVIOUS Q: swiftui, animation applied to parent effect child animation

Now the TextView has its own state. RectangleView with TextView slide into screen in 3 seconds, but state of TextView changed after a second while sliding. Now you can see TextView stops sliding, go to the destination at once. I Just want RectangleView with TextView as a whole when sliding, and TextView rotates or keeps still as I want.

demo gif

import SwiftUI

struct RotationEnvironmentKey: EnvironmentKey {
    static let defaultValue: Bool = false
}

extension EnvironmentValues {
    var rotation: Bool {
        get { return self[RotationEnvironmentKey] }
        set { self[RotationEnvironmentKey] = newValue }
    }
}

struct AnimationTestView: View {
    @State private var go = false
    @State private var rotation = false
    var body: some View {
        VStack {
            Button("Go!") {
                go.toggle()
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                    rotation.toggle()
                    print("set rotation = \(rotation)")
                }
            }
            Group {
                if go {
                    RectangleView()
                        .transition(.slide)
                        .environment(\.rotation, rotation)
                }
            }.animation(.easeInOut(duration: 3.0), value: go)
        }.navigationTitle("Animation Test")
    }
}

struct RectangleView: View {
    var body: some View {
        Rectangle()
            .frame(width: 200, height: 100)
            .foregroundColor(.pink)
            .overlay(TextView())
    }
}

struct TextView: View {
    @Environment(\.rotation) var rotation
    @State private var animationRotating: Bool = false
    let animation = Animation.linear(duration: 3.0).repeatForever(autoreverses: false)
    
    var body: some View {
        print("refresh, rotation = \(rotation)"); return
        HStack {
            Spacer()
            if rotation {
                Text("R")
                    .foregroundColor(.blue)
                    .rotationEffect(.degrees(animationRotating ? 360 : 0))
                    .animation(animation, value: animationRotating)
                    .onAppear { animationRotating = true }
                    .onDisappear { animationRotating = false }
            } else {
                Text("S")
            }
        }
    }
}


Solution 1:[1]

I found the issue here: cannot use if cause in TextView, because when rotation changed, will create a new Text in new position, so we can see the R 'jump' to the right position.

code as following:

Text(rotation ? "R" : "S") .foregroundColor(rotation ? .blue : .white) .rotationEffect(.degrees(animationRotating ? 360 : 0)) .animation(rotation ? animation : nil, value: animationRotating) .onChange(of: rotation) { newValue in animationRotating = true }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 foolbear