Home > Software design >  How to move text and change it's value at the same time in SwiftUI?
How to move text and change it's value at the same time in SwiftUI?

Time:01-10

For example, this is what happening right now

struct ContentView: View {
    @State var titleLable = "This is basic text"
    @State var isTextAnimated: Bool = false
    var body: some View {
        VStack {
            Text(titleLable)
                .offset(y: isTextAnimated ? 300 : 0)
                .animation(.linear)
            Button {
                isTextAnimated.toggle()
                if isTextAnimated {
                    titleLable = "New text appeared"
                } else {
                    titleLable = "This is basic text"
                }
            } label: {
                Text("Press")
            }
        }
        .padding()
    }

The code above leads to this in Live Preview: click there

This happens if text doesn't change its value ( I need this behaviour with changing ): click there

CodePudding user response:

A good way to animate such change is to animate the offset value rather than toggle a boolean:

struct AnimationsView: View {
    @State private var title = "This is basic text"
    @State private var offset: CGFloat = 0

    var body: some View {
        VStack {
            Text("Some text")
                .offset(y: offset)

            Button("Press me") {
                withAnimation {
                    // If we already have an offset, jump back to the previous position
                    offset = offset == 0 ? 300 : 0
                }
            }
        }
    }
}

or by using a boolean value:

struct AnimationsView: View {
    @State private var title = "This is basic text"
    @State private var animated = false

    var body: some View {
        VStack {
            Text("Some text")
                .offset(y: animated ? 300 : 0)

            Button("Press me") {
                withAnimation {
                    animated.toggle()
                }
            }
        }
    }
}

Note the important withAnimation that indicates to SwiftUI that you want to animate the changes made in the block. You can find the documentation here

The .animation(...) is optional and used if you want to change the behavior of the animation, such as using a spring, changing the speed, adding a delay etc... If you don't specify one, SwiftUI will use a default value. In a similar fashion, if you don't want a view to animate, you can use add the .animation(nil) modifier to prevent SwiftUI from animating said view.

Both solutions provided result in the following behavior : https://imgur.com/sOOsFJ0

CodePudding user response:

To animate the position and the content of the Text label, you can use matchedGeometryEffect, as follows:

struct ContentView: View {
    @State var isTextAnimated: Bool = false
    @Namespace var namespace
    
    var body: some View {
        VStack {
            if isTextAnimated {
                Text("New text appeared")
                    .matchedGeometryEffect(id: "title", in: namespace)
                    .offset(y: 300)
            } else {
                Text("This is basic text")
                    .matchedGeometryEffect(id: "title", in: namespace)
            }
            Button {
                withAnimation {
                    isTextAnimated.toggle()
                }
            } label: {
                Text("Press")
            }
        }
        .padding()
    }
}
  • Related