I'm writing a SwiftUI app in which I'd like to have objects animate slowly when they change location and quickly when they disappear. I can't figure out how to achieve that.
Take this example. There are 8 slots, left to right. Each has a box that it can show in one of three "positions": ➊ top, ➋ bottom, or ➌ not at all. When a button is pressed, each box changes location in its slot, meaning that it can appear, disappear, or move (top ↔ bottom). Here's what it looks like:
And the code that produces it:
enum Pos: Int, CaseIterable { case up = 0, down, none /// randomly return a _different_ value from the current one var newValue: Pos { Pos(rawValue: (rawValue+Int.random(in: 1...2)) % 3)!} } struct ContentView: View { /// The positions of 8 squares @State private var posArray: [Pos] = Array(repeating: Pos.none, count: 8).map{$0.newValue} var body: some View { VStack { HStack(spacing: 1) { ForEach(0 ..< posArray.count, id: \.self) { i in VStack(spacing: 0) { // Spacer block on top (if needed) if posArray[i] != .up { Color.clear.frame(width: 40, height: 40) } // Numbered block (if needed) Group { if posArray[i] != .none { Color.primary .frame(width: 40, height: 40) .overlay { Text((i+1).formatted()) .foregroundStyle(.background) } } } .transition(.move(edge: posArray[i] == .up ? .top : .bottom) .combined(with: .opacity)) // Spacer block on top (if needed) if posArray[i] != .down {Color.clear.frame(width: 40, height: 40) } } } }.padding(4).border(Color.green, width: 2) Button("Animate Change") { posArray = posArray.map{ $0.newValue } } }.padding(20) .animation(.easeOut(duration: 2), value: posArray) } } I want just the transitions (i.e., appear/disappear) to animate quickly with Animation.easeOut(duration:0.5) but don't know how to achieve that.
In SwiftUI one can animate different modifiers differently by nesting multiple instances of .animation(), and placing the modifiers at different levels of nesting. But this approach doesn't work with .transition. (If I place one .animation() inside the .transition and one outside, the inner animation winds up applying to everything.)
Also, I am seeking a solution that uses implicit animation. It might be possible to refactor the example here to use .withAnimation() (an explicit animation), but it would be difficult to apply that to actual app I need to create.


