0

I'm still learning and trying to understand the ins and outs of swiftUI. Currently, I focus on understanding gestures and animations and here is an issue that seems unsolvable at my experience level:

The problem: I experience unexpected behavior if the longPressGesture is canceled, eg. lifting the finger before the minimumDuration of the longPress is exceeded.

progress bar animation issue on cancel

The expected result: In the example above you see me long pressing 2 times and afterward canceling the long-press once. I would expect the red progress bar to scale down again and keep its position centered if the longPress was canceled. But as you can see, the progress bar changes its position.

What is causing this issue and how could it be solved while still using swiftUI and GestureState

Here is the code:


struct DiamondPress: View {
    
    @GestureState var isDetectingLongPress = false
    @State var completedLongPress = false
    
    var longPress: some Gesture {
        LongPressGesture(minimumDuration: 2)
        .updating($isDetectingLongPress) { currentState, gestureState, transaction in
            gestureState = currentState
            transaction.animation = Animation.linear(duration: 2.0)
        }
        .onEnded { _ in
            self.completedLongPress.toggle()
        }
    }

    var body: some View {
        
        ZStack {           
            Color.offWhite
            
            RoundedRectangle(cornerRadius: 12, style: .continuous)
            .frame(width: 100, height: 100, alignment: .center)
            .foregroundColor(.white)
            .scaleEffect(completedLongPress ? 2.0 : 1.0)
            .gesture(longPress)
            .animation(.easeIn(duration: 0.2))
                
            // here is the red progress bar:
            Rectangle()
            .frame(
               width: !isDetectingLongPress ? CGFloat(5) : CGFloat(100),
               height: 5, alignment: .center
            )
            .foregroundColor(.red)
        }
        .edgesIgnoringSafeArea(.all)
    }
}

Thanks a bunch, any help or hint is highly appreciated.

nevrx
  • 37
  • 6
  • 1
    Remove animation from update function and set after Rectangle() frame ```Rectangle().frame( width: !isDetectingLongPress ? CGFloat(5) : CGFloat(100), height: 15 ) .animation(Animation.easeInOut(duration: 2))``` – Raja Kishan Jul 10 '21 at 15:40
  • Thanks Raja, in a way it's a good supplement for the updating function. To fully mimic the same behaviour of the updating, one could make the duration conditional: `.animation(Animation.easeInOut(duration: isDetectingLongPress ? 2 : 0))` Still, if someone stumbles upon this who could explain why the updating function doesn't work as I expected, I'd appreciate. – nevrx Jul 11 '21 at 21:09

0 Answers0