Article source address :swiftui-lab.com/advanced-tr…

Author: Javier

Translation: Liaoworking

SwiftUI Advanced Transition Animation

In this article we will explore the different forms of transition from simple to complex, and discuss some different aspects. How to configure, compose, and trigger transitions. We are going to learn what an early transition animation is. But first make sure you are familiar with some of the concepts mentioned earlier.

What is transition animation?

The transition animation determines the effect of inserting or deleting a view in the hierarchy. The transition animation doesn’t work on its own, it needs to work with the animation. Such as:

Note that after XCode11.2, transition animations no longer work with implicit animations. So the following code only works with older versions of Xcode. Fortunately, the other examples are not version dependent. Thank you Tyler Casselman for reminding us in the comments.

struct ContentView: View { @State private var show = false var body: some View { VStack { Spacer() if show { LabelView() .animation(.easeInOut(duration: Transition (.opacity)} Spacer() Button("Animate") {self.show.toggle()}.padding(20)}} struct LabelView: View { var body: some View { Text("Hi there!" ) .padding(10) .font(.title) .foregroundColor(.white) .background(RoundedRectangle(cornerRadius: 8).fill(Color.green).shadow(color: .gray, radius: 3)) } }Copy the code

If you are not familiar with what implicit and display Animations are, you can look at my previous article, Advanced SwiftUI Animations, and for the examples above, you can use both Animations. As follows.

if show { LabelView() .transition(.opacity) } Spacer() Button("Animate") { withAnimation(.easeInOut(duration: 1)) {self.show.toggle()}}.padding(20)Copy the code

Another way is to associate animations with transitions. Note that animations work on transitions, not views (for example, in.transition()).

if show { LabelView() .transition(AnyTransition.opacity.animation(.easeInOut(duration: Spacer() Button("Animate") {self.show.toggle()}.padding(20)Copy the code

Asymmetrical transition

Typically, transitions work when a view is added to the view hierarchy. When the view is removed, it has the opposite effect. Opacity will fade when adding a view. It fades out when you remove it. That can change.

If we want to specifically add or remove animations, we can use the.asymmetric option.

.transition(.asymmetric(insertion: .opacity, removal: .scale))
Copy the code

Combination of the transition

If you want to use several transitions during the transition, for example add a fade in effect while sliding. You can use the following transition:

.transition(AnyTransition.opacity.combined(with: .slide))
Copy the code

Note that you can use both. Asymmetric and. Combined

.transition(.asymmetric(insertion: AnyTransition.opacity.combined(with: .slide), removal: .scale))
Copy the code

Conversion with parameters

Opacity,.slide, and.scale have no parameters. However, some transitions can add additional parameters as follows:

.scale(scale: 0.0, Anchor: UnitPoint(x: 1, y: 0)).scale(scale: 2.0).move(edge:.leading).offset(x: 30).offset(y: 50) .offset(x: 100, y: 10)Copy the code

Custom transitions, an interesting start

Let’s get started

How does transition work?

Inside the system, custom transitions and library transitions work on the same principle, each requiring a modifier for the beginning and end of the animation. Whenever the difference between two decorator components is mutable, swiftUI handles it itself. While we assume that the.opacity transition does not exist, we need to create a custom one called.myopacity. Here is the concrete implementation.

 extension AnyTransition {
    static var myOpacity: AnyTransition { get {
        AnyTransition.modifier(
            active: MyOpacityModifier(opacity: 0),
            identity: MyOpacityModifier(opacity: 1))
        }
    }
}

struct MyOpacityModifier: ViewModifier {
    let opacity: Double
    
    func body(content: Content) -> some View {
        content.opacity(opacity)
    }
}
Copy the code

Now you just use it as a normal transition.

.transition(.myOpacity)
Copy the code

As you can see, we created an extension for AnyTransition. Here we specify two modifiers to create transitions. One is used to start and one is used to end, and SwiftUI uses these modifiers in reverse when removing a view.

Transitions at Full Throttle

With what we know now, we can create new transitions that open up new possibilities for existing.rotationEffect() or.transformeffect (). But when you’re trying to write a new transition, you may find that you don’t know where to start. But you can use all the knowledge in SwiftUI Advanced Animation. When GeometryEffect and Shapes become useful.

Custom transition with GeometryEffect.

Transitions are especially good for popping and folding a panel. If you want to create your own modal system, you should read the following.

Our next exercise is to create a simple transition to show how to pop and collapse a view, okay

extension AnyTransition { static var fly: AnyTransition { get { AnyTransition.modifier(active: FlyTransition(pct: 0), identity: FlyTransition(pct: 1)) } } } struct FlyTransition: GeometryEffect { var pct: Double var animatableData: Double { get { pct } set { pct = newValue } } func effectValue(size: CGSize) -> ProjectionTransform { let rotationPercent = pct let a = CGFloat(Angle(degrees: 90 * (1-rotationPercent)).radians) var transform3d = CATransform3DIdentity; transform3d.m34 = -1/max(size.width, size.height) transform3d = CATransform3DRotate(transform3d, a, 1, 0, 0) transform3d = CATransform3DTranslate(transform3d, -size.width/2.0, -size.height/2.0, 0) let affineTransform1 = ProjectionTransform(CGAffineTransform(translationX: size.width/2.0, y: translationX: size.width/2.0) Size. Height / 2.0)) let affineTransform2 = ProjectionTransform(CGAffineTransform(scaleX: CGFloat(PCT * 2), y: CGFloat(PCT * 2))) if PCT <= 0.5 {return ProjectionTransform(transform3d).concatenating(affineTransform2).concatenating(affineTransform1) } else { return ProjectionTransform(transform3d).concatenating(affineTransform1) } } }Copy the code

The code is transiftion-present-dismiss. Swift

Custom transitions created with Shapes

Another useful use scenario is to animate transitions between two views, one fading in and the other fading out. Our first instinct is to put the two views in a Zstack and change their transparency. That’s fine, but there are other ways to make something cooler.

Code: The transiftion-present-dismiss. Swift sample code requires you to add 4 images to your asset Catalog (named photo1, photo2, photo3, and photo4). This sample is designed for vertical and horizontal screens of the iPad.

If you look at the code in the GIST file, all transitions follow the same pattern, using Animated Shapes to crop incoming and outgoing images. And because they’re Z-STACKED, we have a nice crossover effect.

conclusion

In this article, we don’t say you need to create your own SwiftUI transitions, you need to free your imagination to create your own cool special effects.

If you want to know the latest articles, feel free to comment and follow me on Twitter. See you next time.