I have several UIViews that the user should be able to drag & drop. I use UIPanGestureRecognizer to manage the d&d action (see code below).
This is all possible using Interface Builder. Here is the code I used to do this:
@property (weak,nonatomic) IBOutlet NSLayoutConstraint *buttonXConstraint;
@property (weak,nonatomic) IBOutlet NSLayoutConstraint *buttonYConstraint;
Then hook up those IBOutlets to the Horizontal Constraint(X Position) and Vertical Constraint(Y Position) in the Interface Builder. Make sure that the Constraints are hooked up to the base view and not it's closest view.
Hook up a pan gesture and then use this following code to drag your object around:
- (IBAction)panPlayButton:(UIPanGestureRecognizer *)sender
{
if(sender.state == UIGestureRecognizerStateBegan){
} else if(sender.state == UIGestureRecognizerStateChanged){
CGPoint translation = [sender translationInView:self.view];
//Update the constraint's constant
self.buttonXConstraint.constant += translation.x;
self.buttonYConstraint.constant += translation.y;
// Assign the frame's position only for checking it's fully on the screen
CGRect recognizerFrame = sender.view.frame;
recognizerFrame.origin.x = self.buttonXConstraint.constant;
recognizerFrame.origin.y = self.buttonYConstraint.constant;
// Check if UIImageView is completely inside its superView
if(!CGRectContainsRect(self.view.bounds, recognizerFrame)) {
if (self.buttonYConstraint.constant < CGRectGetMinY(self.view.bounds)) {
self.buttonYConstraint.constant = 0;
} else if (self.buttonYConstraint.constant + CGRectGetHeight(recognizerFrame) > CGRectGetHeight(self.view.bounds)) {
self.buttonYConstraint.constant = CGRectGetHeight(self.view.bounds) - CGRectGetHeight(recognizerFrame);
}
if (self.buttonXConstraint.constant < CGRectGetMinX(self.view.bounds)) {
self.buttonXConstraint.constant = 0;
} else if (self.buttonXConstraint.constant + CGRectGetWidth(recognizerFrame) > CGRectGetWidth(self.view.bounds)) {
self.buttonXConstraint.constant = CGRectGetWidth(self.view.bounds) - CGRectGetWidth(recognizerFrame);
}
}
//Layout the View
[self.view layoutIfNeeded];
} else if(sender.state == UIGestureRecognizerStateEnded){
}
[sender setTranslation:CGPointMake(0, 0) inView:self.view];
}
I have added code in there to check the frame and make sure that it's not going outside the view. If you want to allow the object to be partially off the screen, feel free to take it out.
This took a little bit of time for me to realize that it was the use of AutoLayout that was resetting the view but constraints will do what you need here!