UIGestureRecognizer如何识别哪个圈子被点击?

时间:2016-02-05 10:49:15

标签: ios objective-c iphone

我正在尝试点击五个圆圈中的一个并开始一个动画,该动画将逐渐将所选背景更改为与所拍圆圈相同的颜色。我已经设法让UITapGestureRecognizer响应五个圆圈中的任何一个的轻击手势,但我无法弄清楚如何找出如何识别每个圆圈。

关于UIGestureRecognizer的UIKit框架参考文档说

  

手势识别器根据特定视图的热门测试进行操作   以及该视图的所有子视图

那个

  

手势识别器的客户端也可以询问a的位置   通过调用locationInView:或locationOfTouch:inView“。

这让我觉得可能需要将拍过的圆圈制成图像。

但这真的是我需要做的吗?

这是迄今为止的代码

#import "ViewController.h"
@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

self.view.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];

[self.view setUserInteractionEnabled:YES];

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(method:)];
tap.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tap];    

CAShapeLayer *circleLayer1 = [CAShapeLayer layer];
[circleLayer1 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(75.0,  260.0, 50.0, 50.0)] CGPath]];
[circleLayer1 setStrokeColor:[[UIColor cyanColor] CGColor]];
[circleLayer1 setFillColor:[[UIColor cyanColor] CGColor]];
[[self.view layer] addSublayer:circleLayer1];    

CAShapeLayer *circleLayer2 = [CAShapeLayer layer];
[circleLayer2 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(125.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer2 setStrokeColor:[[UIColor redColor] CGColor]];
[circleLayer2 setFillColor:[[UIColor redColor] CGColor]];
[[self.view layer] addSublayer:circleLayer2];    

CAShapeLayer *circleLayer3 = [CAShapeLayer layer];
[circleLayer3 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(175.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer3 setStrokeColor:[[UIColor yellowColor] CGColor]];
[circleLayer3 setFillColor:[[UIColor yellowColor] CGColor]];
[[self.view layer] addSublayer:circleLayer3];
CAShapeLayer *circleLayer4 = [CAShapeLayer layer];

[circleLayer4 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(225.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer4 setStrokeColor:[[UIColor magentaColor] CGColor]];
[circleLayer4 setFillColor:[[UIColor magentaColor] CGColor]];
[[self.view layer] addSublayer:circleLayer4];

CAShapeLayer *circleLayer5 = [CAShapeLayer layer];
[circleLayer5 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(275.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer5 setStrokeColor:[[UIColor greenColor] CGColor]];
[circleLayer5 setFillColor:[[UIColor greenColor] CGColor]];
[[self.view layer] addSublayer:circleLayer5];
}

- (void)method:(id)sender {
[UIView animateWithDuration:3.0 animations:^{
self.view.layer.backgroundColor = [UIColor cyanColor].CGColor;
} completion:NULL];
}

为了显示我正在尝试做的事情,我已经设置了方法,因此它将背景图层更改为左侧圆圈的颜色。

但我需要做什么[a]来识别哪个圆圈被点击,[b]将点击的圆点表示为圆圈,这些圆圈也会逐渐改变颜色,以便整个屏幕变为被点击的圆圈的颜色?

4 个答案:

答案 0 :(得分:1)

我建议您删除添加到整个视图的UITapGestureRecognizer。 然后为每个CAShapeLayer添加一个名称,以便区分它们:

self.view.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];

[self.view setUserInteractionEnabled:YES];

CAShapeLayer *circleLayer1 = [CAShapeLayer layer];
[circleLayer1 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(75.0,  260.0, 50.0, 50.0)] CGPath]];
[circleLayer1 setStrokeColor:[[UIColor cyanColor] CGColor]];
[circleLayer1 setFillColor:[[UIColor cyanColor] CGColor]];
[circleLayer1 setName:@"circleLayer1"];
[[self.view layer] addSublayer:circleLayer1];

CAShapeLayer *circleLayer2 = [CAShapeLayer layer];
[circleLayer2 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(125.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer2 setStrokeColor:[[UIColor redColor] CGColor]];
[circleLayer2 setFillColor:[[UIColor redColor] CGColor]];
[circleLayer2 setName:@"circleLayer2"];
[[self.view layer] addSublayer:circleLayer2];

CAShapeLayer *circleLayer3 = [CAShapeLayer layer];
[circleLayer3 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(175.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer3 setStrokeColor:[[UIColor yellowColor] CGColor]];
[circleLayer3 setFillColor:[[UIColor yellowColor] CGColor]];
 [circleLayer3 setName:@"circleLayer3"];
[[self.view layer] addSublayer:circleLayer3];
CAShapeLayer *circleLayer4 = [CAShapeLayer layer];

[circleLayer4 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(225.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer4 setStrokeColor:[[UIColor magentaColor] CGColor]];
[circleLayer4 setFillColor:[[UIColor magentaColor] CGColor]];
 [circleLayer4 setName:@"circleLayer4"];
[[self.view layer] addSublayer:circleLayer4];

CAShapeLayer *circleLayer5 = [CAShapeLayer layer];
[circleLayer5 setPath:[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(275.0, 260.0, 50.0, 50.0)] CGPath]];
[circleLayer5 setStrokeColor:[[UIColor greenColor] CGColor]];
[circleLayer5 setFillColor:[[UIColor greenColor] CGColor]];
[circleLayer5 setName:@"circleLayer5"];
[[self.view layer] addSublayer:circleLayer5];

然后你可以添加这个方法,让你能够检测到触及了CAShapeLayer:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches) {
        CGPoint touchLocation = [touch locationInView:self.view];
        for (id sublayer in self.view.layer.sublayers) {
            if ([sublayer isKindOfClass:[CAShapeLayer class]]) {
                CAShapeLayer *shapeLayer = sublayer;
                if (CGPathContainsPoint(shapeLayer.path, 0, touchLocation, YES)) {
                NSLog(@"Layer's name is: %@",shapeLayer.name);
                }
            }
        }
    }
}

现在您可以检测到哪个CAShapeLayer已被触摸,您可以根据需要自定义视图的颜色

答案 1 :(得分:1)

有一种名为locationInView:(UIView *)view的方法可以帮助您找到位置。您知道所有圈子的位置,并使用方法CGRectContainsPoint(CGRect rect, CGPoint point)检查位置是否位于任何矩形内部。如果位于其中,您可以检查所选位置与radius的距离是否centre 。希望这能解决你的问题。

对于Q.(b)我附上了一个你可以参考的样本,

UIColor *stroke = rippleColor ? rippleColor : [UIColor colorWithWhite:0.8 alpha:0.8];

    CGRect pathFrame = CGRectMake(-CGRectGetMidX(self.bounds), -CGRectGetMidY(self.bounds), self.bounds.size.width, self.bounds.size.height);
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:pathFrame cornerRadius:self.layer.cornerRadius];

    // accounts for left/right offset and contentOffset of scroll view
    CGPoint shapePosition = [self convertPoint:self.center fromView:nil];

    CAShapeLayer *circleShape = [CAShapeLayer layer];
    circleShape.path = path.CGPath;
    circleShape.position = shapePosition;
    circleShape.fillColor = [UIColor clearColor].CGColor;
    circleShape.opacity = 0;
    circleShape.strokeColor = stroke.CGColor;
    circleShape.lineWidth = 3;

    [self.layer addSublayer:circleShape];


    [CATransaction begin];
    //remove layer after animation completed
    [CATransaction setCompletionBlock:^{
        [circleShape removeFromSuperlayer];
    }];

    CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(2.5, 2.5, 1)];

    CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    alphaAnimation.fromValue = @1;
    alphaAnimation.toValue = @0;

    CAAnimationGroup *animation = [CAAnimationGroup animation];
    animation.animations = @[scaleAnimation, alphaAnimation];
    animation.duration = 0.5f;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [circleShape addAnimation:animation forKey:nil];

    [CATransaction commit];
}

[UIView animateWithDuration:0.1 animations:^{
    imageView.alpha = 0.4;
    self.layer.borderColor = [UIColor colorWithWhite:1 alpha:0.9].CGColor;
}completion:^(BOOL finished) {
    [UIView animateWithDuration:0.2 animations:^{
        imageView.alpha = 1;
        self.layer.borderColor = [UIColor colorWithWhite:0.8 alpha:0.9].CGColor;
    }completion:^(BOOL finished) {
        if([superSender respondsToSelector:methodName]){
            [superSender performSelectorOnMainThread:methodName withObject:nil waitUntilDone:NO];
        }

        if(_block) {
            BOOL success= YES;
            _block(success);
        }
    }];

}];

}`

答案 2 :(得分:1)

正如其他人的答案所指出的那样,你有一些选择,但我认为最简单的方法是检查你的方法你点了什么图层。

您只需要将方法改为:

- (void)method:(UITapGestureRecognizer *)gesture {
    CGPoint touchLocation = [gesture locationInView:self.view];
    for (id sublayer in self.view.layer.sublayers) {
        if ([sublayer isKindOfClass:[CAShapeLayer class]]) {
            CAShapeLayer *shapeLayer = sublayer;
            if (CGPathContainsPoint(shapeLayer.path, 0, touchLocation, YES)) {
                [UIView animateWithDuration:3.0 animations:^{
                    shapeLayer.strokeColor = [UIColor blackColor].CGColor;
                    shapeLayer.fillColor = [UIColor blackColor].CGColor;
                } completion:NULL];
            }
        }
    }

}

答案 3 :(得分:1)

您不需要在视图中添加任何UITapGestureRecognizer,只需在图层中添加名称并实施以下方法:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    for (UITouch *touch in touches) {
        CGPoint touchLocation = [touch locationInView:self.view];
        for (id sublayer in self.view.layer.sublayers) {
            if ([sublayer isKindOfClass:[CAShapeLayer class]]) {
                CAShapeLayer *shapeLayer = sublayer;
                if (CGPathContainsPoint(shapeLayer.path, 0, touchLocation, YES)) {
                    // This touch is in this shape layer
                    NSLog(@"Name of layer is: %@",shapeLayer.name);   
                }
            } else {
                CALayer *layer = sublayer;
                if (CGRectContainsPoint(layer.frame, touchLocation)) {
                    // Touch is in this rectangular layer
                }
            }
        }
    }
}

识别图层后,您可以相应地更改图层的颜色。

或者,如果您的图层数量有限,则可以按照以下方式识别图层:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
        for (UITouch *touch in touches) {
            CGPoint touchLocation = [touch locationInView:self.view];
            if (CGPathContainsPoint(shape1.path, 0, touchLocation, YES)) {
                // This touch is in this shape layer
                NSLog(@"Name of layer 1 is: %@",shape1.name);
            }
            if (CGPathContainsPoint(shape2.path, 0, touchLocation, YES)) {
                // This touch is in this shape layer
                NSLog(@"Name of layer 2 is: %@",shape2.name);
            }
            if (CGPathContainsPoint(shape3.path, 0, touchLocation, YES)) {
                // This touch is in this shape layer
                NSLog(@"Name of layer 3 is: %@",shape3.name);
            }
            if (CGPathContainsPoint(shape4.path, 0, touchLocation, YES)) {
                    // This touch is in this shape layer
                    NSLog(@"Name of layer 4 is: %@",shape4.name);
                }
            if (CGPathContainsPoint(shape5.path, 0, touchLocation, YES)) {
                    // This touch is in this shape layer
                    NSLog(@"Name of layer 5 is: %@",shape5.name);
                }
        }
    }
相关问题