user1898829
user1898829

Reputation: 3517

UIPanGestureRecognizer when swipe cell for more buttons how to make view bounce back if user swipes less than halfway

enter image description here

I would like that if the user swipes less than half the button width then it bounces back and shows no button but if the user swipes more than half the width of the button then the cell bounces to the right position.

This is what I have so far which makes swiping left and right possible.

private func swipeBothButtonsBothPresent(gesture: UIPanGestureRecognizer) {
    let translation = gesture.translation(in: swipeAbleView)
    guard let gestureView = gesture.view else {
        return
    }
    let center: CGPoint = CGPoint(x: gestureView.center.x + translation.x, y: gestureView.center.y)

    let velocity: CGPoint = gesture.velocity(in: swipeAbleView)
    if velocity.x > 0 {
        //right
        if center.x < swipeAbleView.frame.width / 2 + leftButton.frame.size.width {
            swipeAbleView.center = center
        } else {
            swipeAbleView.center = CGPoint(x: swipeAbleView.frame.width / 2 + leftButton.frame.size.width, y: swipeAbleView.center.y)
        }
    } else {
        //left
        if center.x > swipeAbleView.frame.width / 2 - rightButton.frame.size.width {
            swipeAbleView.center = center
        } else if  isRightButtonThere {
            swipeAbleView.center = CGPoint(x: swipeAbleView.frame.width / 2 - rightButton.frame.size.width, y: swipeAbleView.center.y)
        }
    }
    gesture.setTranslation(CGPoint.zero, in: swipeAbleView)
}

Upvotes: 0

Views: 498

Answers (1)

Khalid Afridi
Khalid Afridi

Reputation: 923

You have to use the UIPangesture states so you can find out what states you're in. you can do that using a switch and check for the .changed, .ended, .cancelled states.

private func swipteBothButtonsBothPresent(with gesture: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: swipeAbleView)

// you can use the center point+velocity to compare to the gestureView center but there is another way as well directly access the translation.x
let center: CGPoint = CGPoint(x: gestureView.center.x + translation.x, y: gestureView.center.y)
let velocity: CGPoint = gesture.velocity(in: swipeAbleView)


// Pan gesture has state which you can access using the gesture you have passed
switch gesture.state {
case .changed:
    // Here you can directly check for translation.x
    /*
    if translation.x < 0 {
        // Do you're calculations
     } else {

     }
    */
    // Your logic to show left or right button
    if velocity.x > 0 {
        //right
        if center.x < swipeAbleView.frame.width / 2 + leftButton.frame.size.width {
            swipeAbleView.center = center
        } else {
            swipeAbleView.center = CGPoint(x: swipeAbleView.frame.width / 2 + leftButton.frame.size.width, y: swipeAbleView.center.y)
        }
    } else {
        //left
        if center.x > swipeAbleView.frame.width / 2 - rightButton.frame.size.width {
            swipeAbleView.center = center
        } else if  isRightButtonThere {
            swipeAbleView.center = CGPoint(x: swipeAbleView.frame.width / 2 - rightButton.frame.size.width, y: swipeAbleView.center.y)
        }
    }

    gesture.setTranslation(CGPoint.zero, in: swipeAbleView)

case .ended:
    // Check here if you have swiped more than buttons half width or lesss you can do it easily using the translation value you have
    // Check if user was swiping left or right you already has the velocity parameter or you can check translation.x to see if the value is negitive or positive (left or right)
    // I cast the translation.x to abs() so even if the value was negitive it will change it back to positive
    // do the check for left or right I have directly added the check for rightButton

    if abs(translation.x) > (rightButton.frame.size.width / 2) {
        // you have dragged more than half of the right button
        // even you can add spring animation to get the bounce effect
        UIView.animate(withDuration: 0.3) {
            // animate back to orignal place
        }
    }

case .cancelled:
    // Do the same dance for cancelled because there can be this state through some times reset add the same code from ended here
    // create a function move the code from .ended state to the function and call the function here
    //
    resetButtons(x: abs(translation.x))
default:
    // there are 3 more states but you can skip them .began, .failed, .possible
    break

}

func resetButtons(x: Int) {
    // Move the code from .ended state of the switch here
}

Upvotes: 1

Related Questions