我有一个UILabel,我添加了一个平移手势识别器,我的视图中还有一个垃圾桶图像,使用UIImage视图。每次我将UILabel拖到垃圾桶图像时,我想从程序视图中删除UILabel。
答案 0 :(得分:9)
我假设你想做这样的事情:
我将告诉你如何实现它。
我们需要一个标签插座和垃圾桶视图的插座:
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIImageView *trashView;
@property (strong, nonatomic) IBOutlet UILabel *label;
@end
将它们连接到您的标签和垃圾桶视图。我们还需要两个实例变量:
@implementation ViewController {
CGPoint labelOriginalCenter;
BOOL trashIsShowingPendingDropAppearance;
}
我们需要保存标签的原始位置,因此如果取消拖动,我们可以将其设置为动画:
- (void)viewDidLoad {
[super viewDidLoad];
labelOriginalCenter = self.label.center;
}
现在让我们为平移手势识别器进行操作。我们需要根据手势移动标签。然后我们需要根据手势的状态采取行动。
- (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;
}
}
要移动标签,我们会通过手势的翻译更改其中心。我们还会在每次更改时将手势的转换重置为零。
- (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;
}
如果手势发生变化,我们会根据触控是否在垃圾桶上更新垃圾桶的外观:
- (void)labelDragDidChange:(UIPanGestureRecognizer *)recognizer {
if ([self dragIsOverTrash:recognizer]) {
[self updateTrashAppearanceForPendingDrop];
} else {
[self updateTrashAppearanceForNoPendingDrop];
}
}
如果手势结束,我们想要丢弃标签,或者根据手势结束时触摸是否在垃圾桶上方中止拖动:
- (void)labelDragDidEnd:(UIPanGestureRecognizer *)recognizer {
if ([self dragIsOverTrash:recognizer]) {
[self dropLabelInTrash];
} else {
[self abortLabelDrag];
}
}
如果手势被取消,我们想要中止拖动:
- (void)labelDragDidAbort:(UIPanGestureRecognizer *)recognizer {
[self abortLabelDrag];
}
要检测手势的触摸是否在垃圾桶上,我们会询问手势识别器在垃圾桶视图的坐标系中的位置。然后我们询问垃圾视图是否该位置在垃圾视图的边界内。
- (BOOL)dragIsOverTrash:(UIPanGestureRecognizer *)recognizer {
CGPoint pointInTrash = [recognizer locationInView:self.trashView];
return [self.trashView pointInside:pointInTrash withEvent:nil];
}
我们可以用很多不同的方式更新垃圾桶的外观。在这里,我们将使垃圾桶在垃圾桶上方摆动时摆动:
- (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];
}
当拖拽离开垃圾桶时,我们需要让垃圾桶停止摆动:
- (void)updateTrashAppearanceForNoPendingDrop {
if (!trashIsShowingPendingDropAppearance)
return;
trashIsShowingPendingDropAppearance = NO;
[UIView animateWithDuration:0.15 animations:^{
self.trashView.transform = CGAffineTransformIdentity;
}];
}
当我们想要将标签丢弃在垃圾箱中时,我们需要做几件事。我们需要阻止垃圾桶摆动,我们需要将标签设置为垃圾桶动画,当动画结束时,我们需要完全删除标签。
- (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;
}];
}
如果拖动被中止,我们需要阻止垃圾桶摆动并将标签动画回原来的位置:
- (void)abortLabelDrag {
[self updateTrashAppearanceForNoPendingDrop];
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.label.center = labelOriginalCenter;
} completion:nil];
}
这就是全部!
答案 1 :(得分:0)
标签可以从手势识别器的视图属性中获取。就垃圾桶而言,您可以使用CGRectIntersectsRect来确定拖动标签的rect是否与垃圾桶的rect重叠。在手势识别器的动作方法中有类似的东西:
- (IBAction)handlePan:(UIPanGestureRecognizer *)sender {
// your other panning code here
if (sender.state == UIGestureRecognizerStateEnded){
if (CGRectIntersectsRect(sender.view.frame, trashcanImageView.frame))
[ sender.view removeFromSuperview];
}
}