I assume you want to do something like this:
I'll show you how to implement that.
We're going to need an outlet for the label and an outlet for the trashcan view:
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIImageView *trashView;
@property (strong, nonatomic) IBOutlet UILabel *label;
@end
Connect these to your label and your trashcan view. We'll also need two instance variables:
@implementation ViewController {
CGPoint labelOriginalCenter;
BOOL trashIsShowingPendingDropAppearance;
}
We need to save the original position of the label, so we can animate it back there if the drag is cancelled:
- (void)viewDidLoad {
[super viewDidLoad];
labelOriginalCenter = self.label.center;
}
Now let's make the action for the pan gesture recognizer. We need to move the label based on the gesture. Then we need to take action based on the state of the gesture.
- (IBAction)labelWasDragged:(UIPanGestureRecognizer *)recognizer {
[self moveLabelForDrag:recognizer];
switch (recognizer.state) {
case UIGestureRecognizerStateChanged:
[self labelDragDidChange:recognizer];
break;
case UIGestureRecognizerStateEnded:
[self labelDragDidEnd:recognizer];
break;
case UIGestureRecognizerStateCancelled:
[self labelDragDidAbort:recognizer];
break;
default:
break;
}
}
To move the label, we change its center by the gesture's translation. We also reset the gesture's translation to zero each time it changes.
- (void)moveLabelForDrag:(UIPanGestureRecognizer *)sender {
CGPoint translation = [sender translationInView:self.label];
[sender setTranslation:CGPointZero inView:self.label];
CGPoint center = self.label.center;
center.x += translation.x;
center.y += translation.y;
self.label.center = center;
}
If the gesture changed, we want to update the appearance of the trash can based on whether the touch is over the trash can:
- (void)labelDragDidChange:(UIPanGestureRecognizer *)recognizer {
if ([self dragIsOverTrash:recognizer]) {
[self updateTrashAppearanceForPendingDrop];
} else {
[self updateTrashAppearanceForNoPendingDrop];
}
}
If the gesture ended, we want to throw away the label, or abort the drag, based on whether the touch was over the trash can when the gesture ended:
- (void)labelDragDidEnd:(UIPanGestureRecognizer *)recognizer {
if ([self dragIsOverTrash:recognizer]) {
[self dropLabelInTrash];
} else {
[self abortLabelDrag];
}
}
If the gesture was cancelled, we want to abort the drag:
- (void)labelDragDidAbort:(UIPanGestureRecognizer *)recognizer {
[self abortLabelDrag];
}
To detect whether the gesture's touch is over the trash can, we ask the gesture recognizer for its location in the trash view's coordinate system. Then we ask the trash view whether that location is inside the trash view's bounds.
- (BOOL)dragIsOverTrash:(UIPanGestureRecognizer *)recognizer {
CGPoint pointInTrash = [recognizer locationInView:self.trashView];
return [self.trashView pointInside:pointInTrash withEvent:nil];
}
We could update the trash can's appearance in lots of different ways. Here, we'll make the trash can wiggle while the drag is over the trash can:
- (void)updateTrashAppearanceForPendingDrop {
if (trashIsShowingPendingDropAppearance)
return;
trashIsShowingPendingDropAppearance = YES;
self.trashView.transform = CGAffineTransformMakeRotation(-.1);
[UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat animations:^{
self.trashView.transform = CGAffineTransformMakeRotation(.1);
} completion:nil];
}
When the drag moves off the trash can, we need to make the trash can stop wiggling:
- (void)updateTrashAppearanceForNoPendingDrop {
if (!trashIsShowingPendingDropAppearance)
return;
trashIsShowingPendingDropAppearance = NO;
[UIView animateWithDuration:0.15 animations:^{
self.trashView.transform = CGAffineTransformIdentity;
}];
}
When we want to drop the label in the trash, we need to do several things. We need to stop the trash can wiggling, we need to animate the label into the trash can, and when the animation ends, we need to remove the label entirely.
- (void)dropLabelInTrash {
[self updateTrashAppearanceForNoPendingDrop];
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.label.center = self.trashView.center;
self.label.transform = CGAffineTransformMakeScale(0.1, 0.1);
} completion:^(BOOL finished) {
[self.label removeFromSuperview];
self.label = nil;
}];
}
If the drag was aborted, we need to stop the trash can wiggling and animate the label back to its original position:
- (void)abortLabelDrag {
[self updateTrashAppearanceForNoPendingDrop];
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.label.center = labelOriginalCenter;
} completion:nil];
}
That's all!