UIButton在设置为UITextField的leftView时接收界外的触摸事件

时间:2013-07-25 17:03:23

标签: iphone ios cocoa-touch

这对我来说有点头疼。在我正在构建的应用程序中,我正在使用UITextField,并添加一个按钮作为leftView属性。然而,似乎在iPad(包括SIM和设备)上,按钮正在接收超出其范围的触摸。当用户触摸占位符文本时,这会干扰UITextField成为第一个响应者的能力。似乎在触摸占位符文本时,事件由按钮而不是文本字段本身处理。奇怪的是,这似乎只发生在iPad上;它在iPhone上按预期工作。

以下是一些展示问题的简单代码:

- (void)viewWillLayoutSubviews {

    [super viewWillLayoutSubviews];

    UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10.0f,
                                                                           10.0f,
                                                                           (self.view.frame.size.width - 20.0f),
                                                                           35.0f)];
    textField.borderStyle = UITextBorderStyleRoundedRect;
    textField.placeholder = @"Test text";
    [self.view addSubview:textField];

    UIButton *addButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
    [addButton addTarget:self action:@selector(touchDown:) forControlEvents:UIControlEventTouchDown];
    [addButton addTarget:self action:@selector(touchUpInside) forControlEvents:UIControlEventTouchUpInside];
    [addButton addTarget:self action:@selector(touchUpOutside) forControlEvents:UIControlEventTouchUpOutside];
    textField.leftView = addButton;
    textField.leftViewMode = UITextFieldViewModeAlways;    
}

- (void)touchDown:(id)sender {
    NSLog(@"touchDown");
}

- (void)touchUpInside {
    NSLog(@"touchUpInside");
}

- (void)touchUpOutside {
     NSLog(@"touchUpOutside");
 }

似乎有时触摸仍然被认为是在内部,即使它们似乎在按钮的界限之外。然后再往前走,按钮只接收UIControlEventTouchDown然后接收UIControlEventTouchUpOutside。

2013-07-25 11:51:44.217 TestApp[22722:c07] touchDown
2013-07-25 11:51:44.306 TestApp[22722:c07] touchUpInside
2013-07-25 11:51:44.689 TestApp[22722:c07] touchDown
2013-07-25 11:51:44.801 TestApp[22722:c07] touchUpOutside

修改 下面是一个示例,其中按钮的背景颜色已更改,以及触发上述事件的大致区域。另外,我检查了按钮的框架,它的宽度小于30px。

Example image

3 个答案:

答案 0 :(得分:4)

我坐了下来,在昨晚花了一些时间。我已经在我的实际应用程序中继承了UITextField,所以我最终覆盖了-(id)hitTest:withEvent:,如下所示。到目前为止,这一直很好。

- (id)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    if ([[super hitTest:point withEvent:event] isEqual:self.leftView]) {
        if (CGRectContainsPoint(self.leftView.frame, point)) {
            return self.leftView;
        } else {
            return self;
        }
    }

    return [super hitTest:point withEvent:event];
}

答案 1 :(得分:1)

我验证了你的结果。我认为这很可能是UITextView中的一个错误。不幸的是,出于某种原因,如果设置leftView,该区域中的事件将被发送到错误的视图(在iPad上)。

我没有一个简单的解决方法,因为调整leftView的框架没有任何效果。我认为它需要修复到比我们可以访问的更低的水平。也许可以向Apple报告这个错误并暂时使用它?

你可以跟踪触摸的位置并忽略它,如果它超出范围,但对于一个小错误似乎很多工作?

答案 2 :(得分:1)

也遇到了这个问题,我发现其他一些解决方案是检查事件点是否位于按钮内。

- (void)touchUpInside:(UIButton *)sender event:(UIEvent *)event
{
    CGPoint location = [[[event allTouches] anyObject] locationInView:sender];

    if (!CGRectContainsPoint(sender.bounds, location)) {
        // Outside of bounds, so ignore:
        return;
    }
    // Inside our bounds, so continue as normal:
}