If you understand correctly, you have two separate problems.
1st: "nonsmooth" drag and drop when using GestureRecognizer. The problem in your code is that you add a translation every time GR calls a processing method. Since the translation is measured continuously, you add a higher value each time it is called (i.e., the first call adds 10 to the split position, 2nd 20th, 3rd, etc.).
To solve this problem, you should set the translation to zero after updating the split position:
- (void)handlePan:(UIPanGestureRecognizer*)recognizer { CGPoint translation = [recognizer translationInView:recognizer.view]; if (recognizer.state == UIGestureRecognizerStateChanged) { self.parentViewController.splitPosition = self.parentViewController.splitPosition + translation.y; } [recognizer setTranslation:CGPointZero inView:recognizer.view]; }
2nd: so that the user can click the split position from the top or bottom, you can check the speed in UIGestureRecognizerStateEnded, and if it returns a certain value, instantly set the splitting to the top or bottom.
But it would be more convenient to use the UISwipeGestureRecognizer.
- (void)handleSwipe:(UISwipeGestureRecognizer *)gr { if (gr.direction == UISwipeGestureRecognizerDirectionUp){ [self.parentViewController moveSplitViewToTop]; } else if (gr.direction == UISwipeGestureRecognizerDirectionDown){ [self.parentViewController moveSplitViewToBottom]; } }
In this case, it may be required (not sure, maybe not) to require SwipeGR to fail before the PanGR triggers install:
[panGestureRecognizer requireGestureRecognizerToFail:swipeGestureRecognizer]
Hope this helps.
Edit: Regarding your comment, I assume that by frequency you mean speed. If you use PanGR, you can change the code above to sth. eg:
- (void)handlePan:(UIPanGestureRecognizer*)recognizer { CGPoint translation = [recognizer translationInView:recognizer.view]; CGPoint velocity = [recognizer velocityInView:recognizer.view]; if (recognizer.state == UIGestureRecognizerStateChanged) { self.parentViewController.splitPosition = self.parentViewController.splitPosition + translation.y; } else if (recognizer.state == UIGestureRecognizerStateEnded){ if (velocity.y > someValue){ [self.parentViewController moveSplitViewToBottom]; } else if (velocity.y < someValue){ [self.parentViewController moveSplitViewToTop]; } } [recognizer setTranslation:CGPointZero inView:recognizer.view]; }
I am not sure if the speed is signed, if not, you need to check the translation in the if-block.