iosswiftswiftuilottie

Lottie file not aligned as expected


I'm using this Lottie library to render a Lottie animation in SwiftUI.

This is my Lottie file, as you can see it is flush against the left margin (left aligned):

Lottie animation

Now I try to load this in my app as follows:

VStack(alignment: .leading, spacing: .zero) {
    LottieView(animation: .named("loading-animation"))
        .playing(loopMode: .loop)
        .frame(height: 40)
}

As you can see here below, the Lottie animation isn't right aligned as I wish and is placed somewhere at the center.

Lottie animation

Not sure why the above code doesn't work as is to align the Lottie animation to the left as if I just use another view with this code (A rectangle for example,) it will be left aligned as expected.

How can I make a Lottie animation view align to the left in SwiftUI?


Solution

  • The alignment on the VStack is used to determine how multiple views inside the VStack should be aligned to each other, if they have different widths. When the VStack only contains one view, it has no effect. The same is true of the spacing.

    I am guessing that the problem is because the content of the VStack (the Lottie animation) is not filling the width of the screen. So the VStack and its contents are shown horizontally centered. If you add a border to the VStack then you will be able to see exactly what width it has.

    To fix, you need to expand the view to fill the width by setting maxWidth: .infinity. At the same time, you can decide how you want it aligned within the wider frame. You don't even need the VStack if it does not have any other content:

    EDIT Thanks for making the animation available. I was able to reproduce the problem. Applying .scaledTofit() before the .frame modifiers gets it working for me:

    LottieView(animation: .named("loading-animation"))
        .playing(loopMode: .loop)
        .scaledToFit()
        .background(.yellow)
        .frame(height: 40)
        .frame(maxWidth: .infinity, alignment: .leading)
    

    Animation

    By examining the JSON file, we can see that the animation has a default size of 320x80. So the code here is maintaining the same aspect ratio but scaling (shrinking) it to fit the height of 40pt.

    If you want to stretch the animation and make it wider then this can be done by applying another scaleEffect to the scaled-down version. To use the full width of the screen, a GeometryReader can be used to measure the available space:

    GeometryReader { proxy in
        let w = proxy.size.width
        let h = proxy.size.height
        let scalingFactor = (w / 320) / (h / 80)
        LottieView(animation: .named("loading-animation"))
            .playing(loopMode: .loop)
            .scaledToFit()
            .background(.yellow)
            .scaleEffect(x: scalingFactor, y: 1, anchor: .leading)
    }
    .frame(height: 40)
    

    Animation