SwiftUI: Animation

Mar 29 2022 · Swift 5.5, iOS 15, Xcode 13

Part 1: Beginning with SwiftUI Animation

08. Interactive Animations

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 07. Multiple Stages Next episode: 9. Conclusion

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 08. Interactive Animations

At this point, you know plenty about creating animations with SwiftUI. But there is one last topic to cover: Creating beautiful animations driven by the user.

In this episode, you’ll add a drag gesture to the spinner control. That’ll give the user the ability to cancel the operation that the spinner represents

i.e. if the spinner shows up while a network request is taking place, swiping down on the spinner will cancel the network operation and hide the spinner view.

To achieve this, start by adding yet another state property to SpinnerView.

  @State var isVisible = true
  @State var currentOffset = CGSize.zero

  let shootUp =

This will keep track of the user’s drag gesture translation whenever a gesture is in progress. Now, add a gesture modifier to your ZStack, with a DragGesture instance.

        }
        .gesture(
          DragGesture()
        )
        .transition(shootUp)

Then, add an onChanged modifier to react to changes in the position of the drag gesture.

          DragGesture()
            .onChanged { gesture in
              currentOffset = gesture.translation
            }
        )

During the gesture, you constantly update currentOffset with the current gesture translation. Next, let’s create a “complete” method.

  }

  func complete() {

  }
  
  func animate() {

Call it when you’re done with the timer, cut the code below that, and paste it in as the body of the complete method.

      if iteration == 30 {
        timer.invalidate()
        complete()
      }
  func complete() {
    completed = true
    currentIndex = -1
    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
      withAnimation {
        isVisible = false
      }
    }
  }

And don’t allow for this code to run, if completed is already true.

  func complete() {
    guard !completed else { return }

    completed = true

Next, add an onEnded modifier. And in its closure, in the case that the user swiped more than 150 points down, call complete().

        .gesture(
          DragGesture()
            .onChanged { gesture in
              currentOffset = gesture.translation
            }
            .onEnded { gesture in
              if currentOffset.height > 150 {
                complete()
              }
            }
        )

Also, reset currentOffset, to animate the spinner back to its original place.

                complete()
              }

              currentOffset = .zero
            }
        )
        .transition(shootUp)

To wrap up, add three more modifiers to your ZStack, which will apply effects to the view during a drag gesture. An offset…

        }
        🟩.offset(currentOffset)
        .gesture(

…and then a blur, for even more visual feedback.

        .offset(currentOffset)
        🟩.blur(radius: currentOffset == .zero ? 0 : 10)
        .gesture(

…and lastly, a 1-second animation.

        .blur(radius: currentOffset == .zero ? 0 : 10)
        🟩.animation(.easeInOut(duration: 1), value: currentOffset)
        .transition(shootUp)

Play the animation, in this completed state, and try dragging the spinner around and then releasing it. If you drag upwards or sideways, the spinner animates back to its original place.

But if you drag it down far enough, that kicks off the completion animation right away.