ios - SwiftUI How to achieve smooth animation of the same view in different stacks - Stack Overflow

admin2025-05-02  0

I set a view, when the state is different, it is in HStack or VStack. But when I set the animation, it does not meet my expectations. I want the view on the right to move up and down smoothly.(position1 moves smoothly to position2)

struct ContentView: View {
    @State var show = false
    var body: some View {
        VStack {
            VStack {
                HStack {
                    Text("test spacer")
                        .contentShape(Rectangle())
                        .frame(minWidth: 0, maxWidth: .infinity)
                        .background(Color.red)
                    if !show {
                        Text("xxxxxx")
                            .background(Color.blue) // position1
                    }
                }
                if show {
                    HStack {
                        Spacer()
                        Text("xxxxxx")
                            .background(Color.blue) // position2
                    }
                }
            }
            .background(Color.yellow)
            .animation(.easeInOut(duration: 1), value: show)

            Button("button") {
                show.toggle()
            }
        }
        .padding()
    }
}

I used Sweeper's answer and used matchedGeometryEffect to solve the problem.

But I tried to change Text to Textfield and changed the timing of triggering the animation to focus. When the keyboard pops up, the animation does not execute smoothly.

How to make the elements in the view slide smoothly?

struct ContentView: View {
    @State private var text = ""
    @Namespace var ns
    @FocusState private var isFocused: Bool
    
    var body: some View {
        ZStack {
            Color.clear
                .contentShape(Rectangle())
                .onTapGesture {
                    isFocused = false
                }
            VStack {
                HStack {
                    TextField("placeholder", text: $text, axis: .vertical)
                        .focused($isFocused)
                        .frame(minHeight: 28)
                        .background(Color.red)
                    if !isFocused {
                        Text("xxxxxx")
                            .background(Color.blue)
                            .matchedGeometryEffect(id: "xxxxxx", in: ns)
                    }
                }
                if isFocused {
                    HStack {
                        Spacer()
                        Text("xxxxxx")
                            .background(Color.blue)
                            .matchedGeometryEffect(id: "xxxxxx", in: ns)
                    }
                }
            }
            .background(Color.yellow)
            .animation(.easeInOut(duration: 1), value: isFocused)
        }
        .padding()
    }
}

I set a view, when the state is different, it is in HStack or VStack. But when I set the animation, it does not meet my expectations. I want the view on the right to move up and down smoothly.(position1 moves smoothly to position2)

struct ContentView: View {
    @State var show = false
    var body: some View {
        VStack {
            VStack {
                HStack {
                    Text("test spacer")
                        .contentShape(Rectangle())
                        .frame(minWidth: 0, maxWidth: .infinity)
                        .background(Color.red)
                    if !show {
                        Text("xxxxxx")
                            .background(Color.blue) // position1
                    }
                }
                if show {
                    HStack {
                        Spacer()
                        Text("xxxxxx")
                            .background(Color.blue) // position2
                    }
                }
            }
            .background(Color.yellow)
            .animation(.easeInOut(duration: 1), value: show)

            Button("button") {
                show.toggle()
            }
        }
        .padding()
    }
}

I used Sweeper's answer and used matchedGeometryEffect to solve the problem.

But I tried to change Text to Textfield and changed the timing of triggering the animation to focus. When the keyboard pops up, the animation does not execute smoothly.

How to make the elements in the view slide smoothly?

struct ContentView: View {
    @State private var text = ""
    @Namespace var ns
    @FocusState private var isFocused: Bool
    
    var body: some View {
        ZStack {
            Color.clear
                .contentShape(Rectangle())
                .onTapGesture {
                    isFocused = false
                }
            VStack {
                HStack {
                    TextField("placeholder", text: $text, axis: .vertical)
                        .focused($isFocused)
                        .frame(minHeight: 28)
                        .background(Color.red)
                    if !isFocused {
                        Text("xxxxxx")
                            .background(Color.blue)
                            .matchedGeometryEffect(id: "xxxxxx", in: ns)
                    }
                }
                if isFocused {
                    HStack {
                        Spacer()
                        Text("xxxxxx")
                            .background(Color.blue)
                            .matchedGeometryEffect(id: "xxxxxx", in: ns)
                    }
                }
            }
            .background(Color.yellow)
            .animation(.easeInOut(duration: 1), value: isFocused)
        }
        .padding()
    }
}

Share Improve this question edited Jan 2 at 7:24 mikko asked Jan 2 at 3:51 mikkomikko 371 silver badge6 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 3

Use a matchedGeometryEffect to "link" the two view's size and position together.

struct ContentView: View {
    @State var show = false
    @Namespace var ns
    var body: some View {
        VStack {
            VStack {
                HStack {
                    Text("test spacer")
                        .contentShape(Rectangle())
                        .frame(minWidth: 0, maxWidth: .infinity)
                        .background(Color.red)
                    if !show {
                        Text("xxxxxx")
                            .background(Color.blue)
                            // here
                            .matchedGeometryEffect(id: "xxxxxx", in: ns)
                    }
                }
                if show {
                    HStack {
                        Spacer()
                        Text("xxxxxx")
                            .background(Color.blue)
                            // and here
                            .matchedGeometryEffect(id: "xxxxxx", in: ns)
                    }
                }
            }
            .background(Color.yellow)
            .animation(.easeInOut(duration: 1), value: show)

            Button("button") {
                show.toggle()
            }
        }
        .padding()
    }
}
转载请注明原文地址:http://anycun.com/QandA/1746135445a92062.html