R. Rincón R. Rincón - 4 months ago 28
Objective-C Question

iOS: How to Enable UIScrollView Panning on Long Press

I can enable/disable scrolling effectively by using the scrollView.scrollEnabled property.

Currently I enable scrolling when the state of the longPressRecognizer is UIGestureStateBegan and disable scrolling when it's UIGestureStateEnded.

When I longPress and then drag my finger, the scrollView doesn't scroll.

I think that somehow the scrollView's panGestureRecognizer isn't getting the touch events, which is weird since the scrollView is (I checked using the touchesBegan, touchesMoved, etc. methods).

Answer

The UIScrollView is not getting touches, because touch started before you enabled scrolling on UIScrollView. This sample code manages scrolling for you with the UILongPressGestureRecognizer, scrolling a big UIImageView:

@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet var gr: UILongPressGestureRecognizer!
var initialPos = CGPointZero
var dragPos = CGPointZero

// This action is bound to long press gesture recognizer within Interface Builder
@IBAction func longpressHandler(sender: UILongPressGestureRecognizer) {
    if sender.state == .Began {
        // Save initial position for moving
        initialPos = sender.locationInView(scrollView)
    }
    else if sender.state == .Changed {
        // Get new drag location
        let loc = sender.locationInView(scrollView)
        let newPos = CGPoint(x: initialPos.x - loc.x + dragPos.x, y: initialPos.y - loc.y + dragPos.y)
        dragPos = newPos
        scrollView.contentOffset = newPos
    }
    else if sender.state == .Ended {
        // Check for end position of the content, snap it back to the edge of the screen if moved too far
        var newOffset = scrollView.contentOffset
        var move = false
        if scrollView.contentOffset.x < 0 {
            newOffset.x = 0
            move = true
        }
        if scrollView.contentOffset.y < 0 {
            newOffset.y = 0
            move = true
        }
        if scrollView.contentOffset.x > photo.frame.size.width - scrollView.frame.size.width {
            newOffset.x = max(self.photo.frame.size.width - self.scrollView.frame.size.width, 0)
            move = true
        }
        if scrollView.contentOffset.y > photo.frame.size.height - scrollView.frame.size.height {
            newOffset.y = max(self.photo.frame.size.height - self.scrollView.frame.size.height, 0)
            move = true
        }
        if move {
            UIView.animateWithDuration(0.25, animations: {
                self.scrollView.contentOffset = newOffset
            })
        }
    }
}

var photo = UIImageView(image: UIImage(named: "photo"))

override func viewDidLoad() {
    super.viewDidLoad()

    // Set up your scrollview
    scrollView.addSubview(photo)
    scrollView.contentSize = photo.frame.size

    // add the long press gesture recognizer to the scrollview
    scrollView.addGestureRecognizer(gr)
}