Removing a UILabel when dragged to an image [close

2020-02-29 19:27发布

I have a UILabel which i added a pan gesture recognizer to and I also have a trashcan image on my view using the UIImage view. I want to delete the UILabel from my program view every time i drag the UILabel to the trashcan image.

2条回答
爷的心禁止访问
2楼-- · 2020-02-29 20:08

The label can be gotten from the gesture recognizer's view property. As far as the trash can, you could use CGRectIntersectsRect to determine if your dragged label's rect overlaps the trashcan's rect. Something like this within the gesture recognizer's action method:

- (IBAction)handlePan:(UIPanGestureRecognizer *)sender {
    // your other panning code here
    if (sender.state == UIGestureRecognizerStateEnded){
        if (CGRectIntersectsRect(sender.view.frame, trashcanImageView.frame))
           [ sender.view removeFromSuperview];
    }
}
查看更多
可以哭但决不认输i
3楼-- · 2020-02-29 20:30

I assume you want to do something like this:

drag demo

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!

查看更多
登录 后发表回答