4

I am trying to create a custom UIControl similar to a slider.

This control is to be the subview of a view that also has a tap gesture recognizer attached to it.

The problem now is that this tap gesture recognizer cancels the touches sent to my control. Is there a way I can override this from within the code of my control?

If I look into the standard controls in iOS it looks as if UIButton has a way of overriding the tap gesture recognizer but UISlider doesn't. So if I replace my custom control with a UIButton the tap gesture recognizer does not trigger its action, but if I replace it with a slider it does.

edit: I made a small project in Xcode to play around in. Download here https://dl.dropboxusercontent.com/u/165243/TouchConcept.zip and try to change it so that

  • The UICustomControl does not know about the tap gesture recognizer
  • The UICustomControl is not cancelled when the user taps down on the yellow box
  • The UICustomControl does not inherit from UIButton (that is a solution that does not feel right and might give me more headaches later on)

The code:

// 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

4 回答 4

5

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

使用手势识别器的委托。

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 不必知道任何同级视图,并且手势识别器不会从我的自定义控件中“窃取”点击,而只会处理“未捕获”的点击。

此外,这样您就不会同时触发手势识别器自定义控件,这会在cancelsTouchesInView中发生。

顺便说一句,也许它可以与 UIButton 一起使用,因为 UIButton 在内部使用手势识别器?我认为他们相互理解,而 UIControls 和识别器则不。不过不确定。

于 2015-03-25T11:17:13.033 回答
5

您可以使用“cancels touches in view”属性将手势识别器配置为不取消它所附加的视图中的触摸:

myGestureRecognizer.cancelsTouchesInView = NO;
于 2013-09-02T15:41:13.410 回答
4

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

    public override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if gestureRecognizer.isKind(of: UITapGestureRecognizer.self) {
            return false
        } else {
            return super.gestureRecognizerShouldBegin(gestureRecognizer)
        }
    }
于 2019-09-25T10:18:10.843 回答
-1

您应该遵循本教程

http://www.raywenderlich.com/1768/uiview-tutorial-for-ios-how-to-make-a-custom-uiview-in-ios-5-a-5-star-rating-view

它向您展示了如何制作自定义 uiview。

然后按照这个 http://www.raywenderlich.com/29474/ipad-for-iphone-developers-101-in-ios-6-custom-input-view-tutorial

于 2013-09-02T16:13:42.377 回答