Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIButton fails to properly register touch in bottom region of iPhone screen

I have an app with many different buttons arranged in a calculator like, square / rectangular format. It is actually extremely similar to the default iOS calculator. There are approximately 6 rows with 4 columns each of buttons.

Problem

The problem I am having involves the buttons in the bottom row (approximately the bottom 10th of the screen on an iPhone 4). They do not behave normally when pressed in the sense that when pressed, they have to be pressed and held (for roughly just under a second) to register a "button press". This is opposed to the standard short tap.

No other buttons besides this bottom row behave in this fashion.

Additionally, if these buttons are tapped on their upper edge, they behave normally, responding as soon as they are touched. This leads me to believe that the buttons themselves are not the problems but there is some problem with the layout of my views.

It should be also noted that this problem is only present on physical devices. On the simulator, the buttons behave normally.

Context

The view containing these buttons is not the root view controller of the app. Instead it is transitioned to as so (nothing fancy here):

[self presentViewController:navController animated:YES completion:nil]; 

Where self is the root view controller

The view controller I am having problems with is contained within a navigation controller and is presented modally by the root view controller which you can see above.

What I have tried so far

  • Turning auto layout on and off: same problem

  • Rearranging hierarchy of views: I moved the problematic buttons on top of and behind all other views with the same result: same problem

  • Multiple devices (iPhone 4, 4s, 5): same problem (although buttons respond normally on both 3.5 inch and 4 inch simulators)

  • Testing other apps (when buttons in this region are pressed on other apps, they behave normally)

Additional Information

  • Everything is laid out in Interface Builder for the problematic view controller
  • All of the buttons are system buttons with standard settings and are all exactly the same besides their text.
  • All of the elements of the screen (buttons, labels, etc. ) are subviews of the "view"
  • The buttons are flush against each other and should not overlap more than one or two pixels.
  • The problematic buttons have dimensions: 80 width X 44 height.
  • The problematic buttons are flush against the bottom of the screen
  • In addition to the buttons, there is one UIImage and several labels however these are at the top of the screen and do not overlap with any of the buttons in any way.
like image 614
Iowa15 Avatar asked Apr 13 '14 18:04

Iowa15


2 Answers

The cause for this issue is that Apple seems to place a GestureRecognizer at the bottom of the screen that delays touches in any other view. After fiddling around with gesture recognizers on the App's windows I came up with a solution that incorporates a subclass of UIButton:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {     BOOL inside = [super pointInside: point withEvent: event];      if (inside && !self.isHighlighted && event.type == UIEventTypeTouches)     {         self.highlighted = YES;     }      return inside; } 

The given method is getting called although touchesBegan: is called delayed. A check if the view is at the bottom of the screen may be suitable to prevent any side effects that may occur with this fix.

like image 158
Quxflux Avatar answered Oct 04 '22 20:10

Quxflux


This sounds like an interaction between the buttons and the UIScreenEdgePanGestureRecognizer (or whatever it is) that is responsible for detecting that the user wants to bring up the system's Control Center.

There are actually two potential issues here:

  • There can be an interaction (i.e. conflict) between the possibility of a gesture directed at your app and a gesture directed at the system. If you have gesture recognizers, you might have to use delegate methods to mediate between them and the system's gesture recognizers.

  • There is a well-established bug where a tap near the screen edge (i.e. in the screen edge gesture recognizer's "zone") works but it causes the button to misbehave physically, i.e. it doesn't look as if it's been tapped even though logging shows that it has (see my answer here: https://stackoverflow.com/a/22000692/341994).

like image 38
matt Avatar answered Oct 04 '22 20:10

matt