Home > OS >  How to reproduce this Objective-C animation with SwiftUI?
How to reproduce this Objective-C animation with SwiftUI?

Time:07-30

I really like SwiftUI and trying to re-build with it an old iPhone app originally created back in 2009. So far, the trickiest part appears to be a particular animation. Here is how it looks in the original:

The animation I'm trying to reproduce

I.e. a view is being updated and also animated, so that its updated copy appears to slide in. Here is the code I am using to achieve this effect:

[self.phaseCell.layer addAnimation:[AnimationManager transitionFromRight] forKey:@"From Right"];

  (CATransition *)transitionFromRight
{
    return [AnimationManager animation:kCATransitionFromRight];
}

  (CATransition *)animation:(NSString *)direction
{
    CATransition *animation = [CATransition animation];
    [animation setDelegate:(id<CAAnimationDelegate>)self];
    [animation setType:kCATransitionPush];
    [animation setSubtype:direction];
    [animation setDuration:0.5f];
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];

    return animation;
}

Is it possible to create something similar with SwiftUI?

CodePudding user response:

here is a demo, triggering the transition on tap:

enter image description here

struct MoonPhase: Identifiable {
    let id = UUID()
    var name: String
    var image: String
}

let phases = [
    MoonPhase(name: "New Moon", image: "moonphase.new.moon"),
    MoonPhase(name: "First Quarter", image: "moonphase.first.quarter"),
    MoonPhase(name: "Full Moon", image: "moonphase.full.moon"),
    MoonPhase(name: "Last Quarter", image: "moonphase.last.quarter"),
]

struct ContentView: View {
    
    @State private var index = 0
    
    var body: some View {
        VStack {
            Divider()
            
            // the interesting part
            HStack {
                Image(systemName: phases[index].image)
                Text(phases[index].name)
            }
            .id(index)
            .frame(maxWidth: .infinity)
            .transition(.asymmetric(insertion: .move(edge: .trailing).combined(with: .opacity),
                                    removal: .move(edge: .leading).combined(with: .opacity)))
            
            Divider()
            
            HStack {
                Image(systemName: "asterisk")
                Text("Moon in Pisces")
            }
            Divider()
        }
        .onTapGesture {
            withAnimation(.easeInOut(duration: 1)) {
                index = (index   1) % phases.count
            }
        }
        .font(.largeTitle)
        .padding()
    }
}
  • Related