Home > Mobile >  Setup UIPanGestureRecognizer for both direction
Setup UIPanGestureRecognizer for both direction

Time:11-04

I'm having a container view and added a UIPanGestureRecognizer on it. It works like this image:

image of container

With the UIPanGestureRecognizer it's possible to swipe to the right, and it works great

    @objc func respondToSwipeRight(recognizer: UIPanGestureRecognizer) {
        
        
        container.setAnchorPoint(anchorPoint: .init(x: 1, y: 1))
        
        
        let touchLocation = recognizer.location(in: container.superview)
        
        let center = container.center
        
        switch recognizer.state{
            
        case .began :
            self.deltaAngle = atan2(touchLocation.y - center.y, touchLocation.x - center.x) - atan2(container.transform.b, container.transform.a)
            
        case .changed:
            
            
            backgroundView.backgroundColor = UIColor.systemGreen
            let angle = atan2(touchLocation.y - center.y, touchLocation.x - center.x)
            
            let angleDiff = self.deltaAngle - angle
            
            if angleDiff <= 0, angleDiff > -5, angleDiff > -0.50 {
                container.transform = CGAffineTransform(rotationAngle: -angleDiff)
            }
            
            
        case .ended:
            UIView.animate(withDuration: 0.6, animations: { [weak self] in
                guard let this = self else { return }
                this.container.transform = CGAffineTransform(rotationAngle: 0)
            }, completion: { [weak self] _ in
                guard let this = self else { return }
                
                this.container.setAnchorPoint(anchorPoint: .init(x: 0.5, y: 0.5))
            })
            
        default: break
            
        }
    }

Now, I want to have the same things from right to left, I added a new UIPanGestureRecognizer to that view, but appearance I only can have one UIPanGestureRecognizer per view and it uses the latest one. Could anyone help me to have the same mechanism for right to left? For right to left, the container anchor point should be like that:

container.setAnchorPoint(anchorPoint: .init(x: 0, y: 1))

Your help will be appreciated

CodePudding user response:

Here's an example of using a single UIPanGestureRecognizer to rotate the box around either the bottom-left or bottom-right corner as the user moves their finger right and left. Be sure to start your pan gesture on the box.

Start with a new iOS app project. Use the following for the ViewController class. No other changes to the project are needed. Run on your favorite iOS device or simulator.

enum PanDirection {
    case unknown
    case left
    case right
}

class ViewController: UIViewController {
    var box: UIView!
    var direction: PanDirection = .unknown

    override func viewDidLoad() {
        super.viewDidLoad()

        let container = UIView(frame: .zero)
        container.backgroundColor = .systemBlue
        container.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(container)

        // Just some example constraints to put the box on the screen
        NSLayoutConstraint.activate([
            container.heightAnchor.constraint(equalToConstant: 250),
            container.widthAnchor.constraint(equalTo: container.heightAnchor),
            container.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -30),
            container.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
        ])

        // The box that will be rotated
        // Sized to match the blue container
        box = UIView(frame: container.bounds)
        box.backgroundColor = .systemGreen
        box.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        container.addSubview(box)

        // Setup the pan gesture and add to the blue container
        let pan = UIPanGestureRecognizer(target: self, action: #selector(panHandler))
        pan.minimumNumberOfTouches = 1
        pan.maximumNumberOfTouches = 1
        container.addGestureRecognizer(pan)
    }

    @objc func panHandler(_ gesture: UIPanGestureRecognizer) {
        if gesture.state == .began || gesture.state == .changed {
            // Relative offset from the start of the gesture
            let offset = gesture.translation(in: gesture.view)

            // Determine which direction we are panning
            if offset.x == 0 {
                direction = .unknown
            } else {
                direction = offset.x > 0 ? .right : .left
            }

            if direction == .right {
                // How far right we have panned
                let right = offset.x

                // Only rotate up to 75 degrees - just an example
                let angleDeg = min(right / box.bounds.size.width * 90, 75)

                // Calculate the transform. We need to translate the box to the bottom-right corner,
                // then rotate, then translate back to the center.
                let shift = CGAffineTransform(translationX: box.bounds.size.width / 2, y: box.bounds.size.height / 2)
                box.transform = shift.rotated(by: angleDeg / 180 * .pi).translatedBy(x: -box.bounds.size.width / 2, y: -box.bounds.size.height / 2)
            } else if direction == .left {
                // How far to the left we have panned
                let left = offset.x

                // Only rotate up to 75 degrees - just an example
                let angleDeg = max(left / box.bounds.size.width * 90, -75)

                // Calculate the transform. We need to translate the box to the bottom-left corner,
                // then rotate, then translate back to the center.
                let shift = CGAffineTransform(translationX: -box.bounds.size.width / 2, y: box.bounds.size.height / 2)
                box.transform = shift.rotated(by: angleDeg / 180 * .pi).translatedBy(x: box.bounds.size.width / 2, y: -box.bounds.size.height / 2)
            }
        } else {
            // Reset for next pan gesture
            direction = .unknown
        }
    }
}

Start a pan in the box - move right and left and the green box rotates back and forth around the appropriate corner as the finger moves.


enter image description here

  • Related