NEW: Learn to build the incredible iOS 15 Weather app today! >>

SOLVED: Pulsating text gets wonky on new sheet

Forums > SwiftUI

I created pulstaing text that works fine on the main view. When the second view appears, it also works fine, but if you scroll up and down several times, the text gets larger and larger. I created this to make the item in the top of the list stand out, but I don't really want it continuing to grow. Sometimes the animation also just stops. It seems like the .onAppear modifier is being invoked multiple times. Is that correct?

struct NewView: View {
    @State private var newAnimationAmount = 1.0
    var body: some View {
        List {
            Text("Don't Tap Me")
                .scaleEffect(newAnimationAmount)
                .animation(
                    .easeInOut(duration: 1)
                        .repeatForever(autoreverses: true),
                    value: newAnimationAmount
                )
                .onAppear {
                    newAnimationAmount += 0.1
                }
            ForEach(1..<100) {
                Text(String($0))
            }
        }
    }
}

struct ContentView: View {
    @State private var animationAmount = 1.0
    @State private var showingAdd = false

    var body: some View {
        Button {
            showingAdd = true
        } label: {
            Text("Tap Me")
        }
        .buttonStyle(.bordered)
        .foregroundColor(.black)
        .scaleEffect(animationAmount)
        .animation(
            .easeInOut(duration: 1)
                .repeatForever(autoreverses: true),
            value: animationAmount
        )
        .onAppear {
            animationAmount += 0.1
        }
        .sheet(isPresented: $showingAdd) {
            NewView()
        }
    }
}

   

It seems like the .onAppear modifier is being invoked multiple times. Is that correct?

Yep. The sheet isn't the problem, the List is. As you scroll your List and rows go offscreen and onscreen, the onAppear fires. (Note that your ContentView, which has no scrolling list, does not exhibit the same issue.) You could attach onAppear to the List itself, not to any item inside the List.

So:

List {
    //blah blah blah
}
.onAppear {
    newAnimationAmount += 0.1
}

That will prevent the text from continuing to enlarge every time you scroll it offscreen and then back onscreen. But it kills the animation.

You can solve both issues this way:

List {
    Text("Don't Tap Me")
        .scaleEffect(newAnimationAmount)
        .animation(
            .easeInOut(duration: 1)
                .repeatForever(autoreverses: true),
            value: newAnimationAmount
        )
        .onAppear {
            newAnimationAmount = 1.1 //set the value explicitly
        }
    ForEach(1..<100) {
        Text(String($0))
    }
}

By setting the max value of newAnimationAmount explicitly, you prevent it from continually increasing as you scroll and the animation works as desired.

   

Thanks for the reply.

I made the change you suggested and when I scroll down and back up, although it doesn't resize anymore, the animation ends. Since you said the List is the problem, I moved the Text out of the List and then it works fine. It changes the layout, of course, but I can play around with that.

Thanks.

   

Hacking with Swift is sponsored by Sentry

SPONSORED With Sentry’s error and performance monitoring for iOS, you see mobile vitals that actually matter, can solve any latency issues quickly, and learn how each release is performing over time.

Learn More

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.