Search code examples
iosobjective-cuiscrollviewuipangesturerecognizercliptobounds

How to dismiss programmatically the clipsToBounds property when a GestureRecognizer begin?


I have a UIScrollView which is able to contains many view. To allow a good scrolling (without the content going outside the view while scrolling), on my Main.sotryboard , I've clicked on my UIScrollView and then in the attribute inspector I have allowed the Clip Subviews property:

The 3rd property is: Clip Subviews

My problem: all the views which are in my UIScrollViews are draggable (because they all have a UIPanGestureRecognizer. So, when I try to drag them OUTSIDE my UIScrollView, they just disappear. In fact they're just going behind every other view

To give you an exemple, I have others components which allow the drop of a view form the precedent UIScrollView. So when I begin the drag'n'drop from it, it disappear, and then reappear in the second component on which I have dropped the view.

What I have tried: I have a special UIPanGestureRecognizer for te drag'n'drop of a view coming from this UIScrollView. So, I actually have this (which, obviously, doesn't work, otherwise I would not be here):

//Here recognizer is the `UIPanGestureRecognizer`
//selectpostit is the name of the view I want to drag
if(recognizer.state == UIGestureRecognizerStateBegan){
    selectpostit.clipsToBounds = NO;
}

Any Ideas on how I can improve that? Thanks in advance.


Solution

  • You could try to reset scrollView.clipsToBounds to NO every time gesture starts, but that would lead to side effect when other content outside scroll view would become visible when dragging is in the progress.

    I would recommend to take snapshot of the the draggable view when panning starts, place it on the scrollview's parent, and move it. Such approach should solve your problem.

    Here is the code:

    - (void)onPanGesture:(UIPanGestureRecognizer*)panRecognizer
    {
        if(panRecognizer.state == UIGestureRecognizerStateBegan)
        {
            //when gesture recognizer starts, making snapshot of the draggableView and hiding it
            //will move shapshot that's placed on the parent of the scroll view
            //that helps to prevent cutting by the scroll view bounds
            self.draggableViewSnapshot = [self.draggableView snapshotViewAfterScreenUpdates: NO];
            self.draggableView.hidden = YES;
            [self.scrollView.superview addSubview: self.draggableViewSnapshot];
        }
    
        //your code that updates position of the draggable view
    
        //updating snapshot center, by converting coordinates from draggable view
        CGPoint snapshotCenter = [self.draggableView.superview convertPoint:self.draggableView.center toView: self.scrollView.superview];
        self.draggableViewSnapshot.center = snapshotCenter;
    
        if(panRecognizer.state == UIGestureRecognizerStateEnded ||
           panRecognizer.state == UIGestureRecognizerStateCancelled ||
           panRecognizer.state == UIGestureRecognizerStateFailed)
        {
            //when gesture is over, cleaning up the snapshot
            //and showing draggable view back
            [self.draggableViewSnapshot removeFromSuperview];
            self.draggableViewSnapshot = nil;
            self.draggableView.hidden = NO;
        }
    }