joekndy / MarqueeText

Marquee or "scrolling text" effect in SwiftUI
270 stars 43 forks source link

Animation broken when inside NavigationView #2

Closed fabiogiolito closed 2 years ago

fabiogiolito commented 4 years ago

Thank you for sharing this code, Joe. I'm just seeing an issue, I wanted to know if you see the same or know what could be going on.

This works great:

HStack {
    Spacer()
    MarqueeText(
        text: "A subtitle that is way too long, but it scrolls homie. A subtitle that is way too long, but it scrolls homie",
        font: UIFont.preferredFont(forTextStyle: .subheadline),
        leftFade: 16,
        rightFade: 16,
        startDelay: 3
     )
    Spacer()
}

This breaks:

NavigationView {
    HStack {
        Spacer()
        MarqueeText(
            text: "A subtitle that is way too long, but it scrolls homie. A subtitle that is way too long, but it scrolls homie",
            font: UIFont.preferredFont(forTextStyle: .subheadline),
            leftFade: 16,
            rightFade: 16,
            startDelay: 3
         )
        Spacer()
    }
}

When it's inside a NavigationView the text moves all the way from the top edge of the screen down to the position it should be, at the same time it's scrolling left.

marquee

fabiogiolito commented 4 years ago

Did some more digging. It seems that theonAppear fires before the view finds its initial size and position, so the implicit Animation is animating from 0,0 position and 0,0 size to the final position.

If you replace onAppear with onTapGesture to test, then tap the element then it works fine because it gives it time to actually appear.

So a workaround I found was to do this:

.onAppear() {
    if geometry.size.width < stringWidth {
        // Give it some time to actually appear
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            self.animate = true
        }
    }
}

I still have no idea why this happens and why only when inside a NavigationView though…

andrewjmeier commented 3 years ago

I'm running into a similar issue. I get the same behavior where the text animates vertically as well. In my case, I have my text scrolling and then if I swap the view with another view and swap back it starts to get distorted. Unlike above, I can't use the dispatch after hack because onAppear isn't called when the view is swapped back. It's properly holding on to its state and continuing the animation where it left off.

andrewjmeier commented 3 years ago

I was able to fix this by adding the value parameter to .animation

drakos commented 3 years ago

@andrewjmeier could you please share your fix with actual code? Many thanks!

andrewjmeier commented 3 years ago

.animation(self.animate ? self.animation : nil, value: self.animate)

PierreCapo commented 3 years ago

Thanks @andrewjmeier this fixes indeed the problem, and I guess it is the right implementation

Semty commented 3 years ago

@andrewjmeier cheers, man, great solution, works like a charm

FleetPhil commented 3 years ago

@andrewjmeier I'm not sure I've understood that correctly as it's still not working for me... To make the animation clearer I've added in the view body:

let animation = Animation.linear(duration: Double(stringWidth) / 30)
   .delay(startDelay)
   .repeatForever(autoreverses: false)

Then updated each of the .animation view modifiers to .animation(self.animate ? animation : nil, value: self.animate) But I still get the same issue where the text is descending and scrolling in the view...

I'm running Xcode 13.1 with a iOS 15 target....