自定义 UIControl 和手势识别器

Kri*_*oot 4 objective-c ios

我正在尝试创建一个类似于滑块的自定义 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
Run Code Online (Sandbox Code Playgroud)

Dav*_*ist 5

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

myGestureRecognizer.cancelsTouchesInView = NO;
Run Code Online (Sandbox Code Playgroud)

  • 我认为这不是解决方案,因为手势识别器仍然会触发其操作。最重要的是,它需要更改控件的某些超级视图中的代码才能使控件正常运行。 (3认同)

Jer*_*uma 5

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

使用手势识别器的委托。

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

然后当手势识别器想要处理/吞下触摸时,在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);
}
Run Code Online (Sandbox Code Playgroud)

我在我的 ViewController 中完成了所有这些,这样 UIControl 就不必知道任何兄弟视图,并且手势识别器不会从我的自定义控件中“窃取”点击,而只处理“未捕获”的点击。

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

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


小智 5

gestureRecognizerShouldBegin(_:)在你的子类中重写UIControl

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