自定义UIControl和手势识别器

时间:2013-09-02 15:37:32

标签: ios objective-c

我正在尝试创建一个类似于滑块的自定义UIControl。

此控件是视图的子视图,该视图还附加了一个轻击手势识别器。

现在的问题是这个点击手势识别器会取消发送到我控件的触摸。有没有办法可以在我的控制代码中覆盖它?

如果我查看iOS中的标准控件,看起来UIButton有一种覆盖轻敲手势识别器的方法,但UISlider却没有。因此,如果我用UIButton替换我的自定义控件,则点按手势识别器不会触发其操作,但如果我用滑块替换它,则会这样做。

编辑:我在Xcode中创建了一个小项目。在这里下载https://dl.dropboxusercontent.com/u/165243/TouchConcept.zip并尝试更改它以便

  • UICustomControl不知道轻敲手势识别器
  • 当用户点击黄色方框时,不会取消UICustomControl
  • UICustomControl不会从UIButton继承(这是一种感觉不对的解决方案,可能会让我后来更加头疼)

代码:

// inherit from UIButton will give the wanted behavior, inherit from UIView (or UIControl) gives
// touchesCancelled by the gesture recognizer
@interface UICustomControl : UIView

@end

@implementation UICustomControl

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{   NSLog(@"touchesBegan"); }

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{   NSLog(@"touchesMoved"); }

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{   NSLog(@"touchesEnded"); }

-(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{   NSLog(@"touchesCancelled"); }

@end
@interface ViewController ()

@end


@implementation ViewController

- (void)viewDidLoad
{
    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(logTap:)];
    [self.view addGestureRecognizer:tapRecognizer];
    UIView *interceptingView = [[UICustomControl alloc]initWithFrame:CGRectMake(10, 10, 100, 100)];
    interceptingView.userInteractionEnabled = YES;
    interceptingView.backgroundColor = [UIColor yellowColor];
    [self.view addSubview: interceptingView];
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void) logTap: (id) sender
{
    NSLog(@"gesture recognizer fired");
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

4 个答案:

答案 0 :(得分:3)

您可以使用“取消触摸视图”属性将手势识别器配置为取消其附加视图中的触摸:

myGestureRecognizer.cancelsTouchesInView = NO;

答案 1 :(得分:3)

我有点晚了,但对于那些(像我一样)绊倒这个问题的人,我使用了另一种解决方案:

使用手势识别器的代理。

UITapGestureRecognizer *tapGestRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissInfoBox:)];
tapGestRec.delegate = self;
[self.view addGestureRecognizer:tapGestRec];

当手势识别器想要处理/吞下触摸时,在 shouldReceiveTouch 委托功能中进行一种命中测试。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint location = [touch locationInView:self.view];
    return !CGRectContainsPoint(self.myCustomControl.frame, location) && !CGRectContainsPoint(self.myOtherCustomControl.frame, location);
}

我在我的ViewController中完成了所有这些操作,这样UIControl就不必知道任何兄弟视图,并且手势识别器不会“偷”'从我的自定义控件中点击,只处理' uncaught'水龙头。

此外,通过这种方式,您不会触发手势识别器自定义控件,这将通过 cancelsTouchesInView 进行。

顺便说一句,也许它适用于UIButton,因为UIButton在内部使用手势识别器?我认为他们互相理解,而UIControls和识别者却没有。但不确定。

答案 2 :(得分:0)

答案 3 :(得分:0)

在您的gestureRecognizerShouldBegin(_:)子类中覆盖UIControl

    public override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if gestureRecognizer.isKind(of: UITapGestureRecognizer.self) {
            return false
        } else {
            return super.gestureRecognizerShouldBegin(gestureRecognizer)
        }
    }