Search code examples
iosswiftuiimageviewswiftui

How to animate images in SwiftUI, to play a frame animation


I want to animate images in SwiftUI's Image view

First, I tried creating some variables and a function to toggle the Image("imageVariable"). It changes but there is no animation even tried the withAnimation { } method

Secondly, I tried to use a UIKit view. Here, the animation works but I can't apply the resizable() modifier or a set a fixed frame

var images: [UIImage]! = [UIImage(named: "pushup001")!, UIImage(named: "pushup002")!]

let animatedImage = UIImage.animatedImage(with: images, duration: 0.5)

struct workoutAnimation: UIViewRepresentable {

    func makeUIView(context: Self.Context) -> UIImageView {
        return UIImageView(image: animatedImage)
    }

    func updateUIView(_ uiView: UIImageView, context: UIViewRepresentableContext<workoutAnimation>) {

    }
}


struct WorkoutView: View {
    var body: some View {
        VStack {
            workoutAnimation().aspectRatio(contentMode: .fit)
        }
    }
}

In method 1 I can change the image but not animate, while, in method 2 I can animate but not control it's size


Solution

  • I solved this using UIViewRepresentable protocol. Here I returned a UIView with the ImageView as it's subview. This gave me more control over the child's size, etc.

    import SwiftUI
    
    
    var images : [UIImage]! = [UIImage(named: "pushup001")!, UIImage(named: "pushup002")!]
    
    let animatedImage = UIImage.animatedImage(with: images, duration: 0.5)
    
    struct workoutAnimation: UIViewRepresentable {
    
        func makeUIView(context: Self.Context) -> UIView {
            let someView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
            let someImage = UIImageView(frame: CGRect(x: 20, y: 100, width: 360, height: 180))
            someImage.clipsToBounds = true
            someImage.layer.cornerRadius = 20
            someImage.autoresizesSubviews = true
            someImage.contentMode = UIView.ContentMode.scaleAspectFill
            someImage.image = animatedImage
            someView.addSubview(someImage)
            return someView
        }
    
        func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<workoutAnimation>) {
    
        }
    }
    
    
    struct WorkoutView: View {
        var body: some View {
            VStack (alignment: HorizontalAlignment.center, spacing: 10) {
                workoutAnimation()
                Text("zzzz")
            }
        }
    }