UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

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()
        }
    }
}

2      

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.

2      

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.

2      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

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

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

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.