3
votes

I am writing an ipad application where you can drag around the screen with 1 or 2 fingers. I use the touchesBegan, touchesMoved and touchesEnded methods to recognize the touches. I have multipletouches enabled for the view.

Now I have recognized one strange behaviour. If I place a finger outside of the upper screen border and drag it down to the screen I won't receive a call to touchesBegan or touchesMoved. This can not be reproduced for the other screen borders.

The only other case where it can be reproduced is when I use landscape orientation with the home button to the left side. In this case I get the same behaviour for the upper screen border.

Has anyone information about this or does experience the same if testing?

Edit: I did some additional testing. The area where the statusbar would normally be is receiving touchesBegan or touchesMoved very fine if i put down the finger in that region or slide it upwards from any lower screen position. The input is not recognized only if i slide the finger down from a position that is completly above the screen edge.

Edit2: Additional Info: - My app uses an OpenGL view. - The statusbar is hidden. - touchesBegan is called properly when touching the (hidden) statusbar areas in all orientations.

3

3 Answers

3
votes

I believe the underlying issue is that the touch-sensitive layer on the screen extends a few pixels above the visible screen, meaning that touches originating there technically start outside your UIViewController view. Since your UIViewController only sees touches that originate within its view, it won't see these touches. So if your device screen is touched a pixel or two above the visible pixels, the touch will be sent to whatever virtual layer exists in that offscreen area (perhaps the status bar?). This prevents your UIViewController from receiving any touches, since the swipe did not originate in your UIViewController's view area.

To work around this, at applicationDidLaunch time you can resize your UIWindow to be (say) 10 pixels larger on each side, and create an intermediate UIViewController 'background' layer inside it, matching the expanded size of the window. Then set your main interface UIViewController view to be a child of the 'background' view, inset 10 pixels on all sides to re-match the physical screen size. If your interface rotates, the 10-pixel enlargement of the background view will have to be re-applied in the willAnimateRotationToInterfaceOrientation method in your background UIViewController each time.

Finally, have the touchesBegan/Moved/Ended methods in the background view controller forward their touches directly to the corresponding methods in your main UI view controller. Voila!

Hope this helps, Ben

0
votes

Sounds right to me. If you drag your finger across the status bar first, it will receive all touch events for this finger until you lift it. All touch events are delivered to the view in which the touch began.

0
votes

unfortunately touchesBegan cannot be called from the status bar area.