Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIButton receiving touch events outside bounds when set as leftView of UITextField

This has been a bit of a head scratcher for me. In an app I'm building I am using a UITextField, and adding a button as the leftView property. However, it seems that on an iPad (both sim and on device), the button is receiving touches that are well outside its bounds. This is interfering with the ability of the UITextField to become the first responder when the user touches the placeholder text. It seems that when touching the placeholder text, the events are being handled by the button instead of the text field itself. Strangely, this only appears to happen on iPad; it works as expected on the iPhone.

Here is some simple code demonstrating the problem:

- (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");
 }

It seems that sometimes touches are still perceived as being inside even though they appear to be outside the button's bounds. Then getting even further right, the button only receives UIControlEventTouchDown then 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

EDIT Here is an example with the background color of the button changed as well as the approximate zones that trigger the events above. Also, I checked the frame of the button and it is less than 30px wide.

Example image

like image 542
Kevin Lord Avatar asked Nov 18 '25 18:11

Kevin Lord


1 Answers

I sat down and spent some more time on this last night. I was already subclassing UITextField in my real application, so I ended up overriding -(id)hitTest:withEvent: as seen below. This has been working fine so far.

- (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];
}
like image 100
Kevin Lord Avatar answered Nov 21 '25 10:11

Kevin Lord



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!