0

Is it possible to control the progress of withAnimation

Ideal API would look something like this

withAnimation(progress: percentDragged) { showSecondView.toggle() }

Here's a full code example of the above line in context.

The goal is to smoothly slide between different app states with a user controlled gesture.

struct ContentView: View {
    
    @State var showSecondView = false

    var body: some View {
        VStack {
            ZStack {
                if !showSecondView {
                    Text("First view")
                        .padding()
                        .background(Color.blue)
                        .transition(.slide)
                } else {
                    Text("Second view")
                        .padding()
                        .background(Color.red)
                        .transition(.slide)
                }
            }
        }
        .gesture(
            DragGesture()
                .onChanged { value in
                    let percentDragged = value.translation.width / UIScreen.main.bounds.width
                    
                    // Here I want to gradually slide (interpolate) between the two states
                    // Ideal API would look like this:
                    withAnimation(progress: percentDragged) { showSecondView.toggle() }
                }
        )
    }
}

Yes.. I know I can trigger an animation whenever I want (like this). but that's not what I'm looking for! I want to control the progress

if percentDragged > 0.5 {
    withAnimation { showSecondView.toggle() }
}

Yes.. I also know I could manually store a @State var offset: Double and control my own slide. This just gets nasty when my app state is tied to tons of different visual changes. Views appearing/disappearing, alignments shifting, etc.

joshuakcockrell
  • 5,200
  • 2
  • 34
  • 47
  • What do you mean by "control"? Are you asking if you can doing something like stop it in the middle? – Yrb Oct 03 '21 at 19:11
  • Does this answer your question https://stackoverflow.com/a/61760123/12299030? – Asperi Oct 03 '21 at 19:15
  • @Yrb "control" means I could manually interpolate between the states with a gesture. Not just tell it to start. The code I posted is a real example of how this would be used. – joshuakcockrell Oct 03 '21 at 19:18
  • @Asperi That link uses a `@State var progress: CGFloat` to track the progress and uses that to interpolate changes. It's definitely a solution (I mentioned it in my last paragraph), just gets nasty when lots of different changes are happening and with if statements. Wondering if there's a cleaner way. – joshuakcockrell Oct 03 '21 at 19:22
  • The way I've done this before (multiple times) in UIKit is to use a UIScrollView to track the gesture and then use the scroll offset to then set the values on the views I want to "animate". It's not actually an animation in the iOS sense of the word as it's not over time. It's just static views based on the scroll offset. I imagine you might be able to do something similar with SwiftUI. But I'm not 100% sure. https://oliverfoggin.com/2014/10/02/controlling-animations-with-a-uiscrollview/ – Fogmeister Oct 03 '21 at 20:06
  • I think you need make your question and example more clear to understand! and make it simple and small as possible! – ios coder Oct 03 '21 at 21:42
  • Isn't that essentially a `PageTabViewStyle`? – Yrb Oct 04 '21 at 00:22
  • I ended up just storing a `@State var progress: Double` and manually updating it with the gesture. – joshuakcockrell Oct 17 '21 at 16:40

0 Answers0