Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I modify touch and drag sensitivity?

Tags:

ios

I'm working on an app for a physically challenged population, and in testing we're finding that they have a lot of trouble with the default touch-drag functionality.

We've got a screen where there's a grid of icons in a UIScrollView. You can touch an icon to activate it, and you can touch-drag anywhere in the grid, including on an icon, to scroll the grid and see more icons.

In iOS, the default behavior is that you touch and drag in one motion. This requires a certain amount of physical coordination, and if you touch and pause and then drag, or drag a little off course, the system treats this as a simple touch. So our testers are doing things like:

  • Touch, pause for a moment, and then try to drag. The grid doesn't scroll. If they were trying to scroll by dragging an icon, when they release the touch, it activates the icon instead.

  • Touch, try to drag vertically (the only supported direction), but instead veer a little bit horizontally first. Same outcome as above.

So the question is: is there a way to override the touch processing to build in more tolerance for slowness or drag inaccuracy, so that the app will correctly interpret the above actions as scroll requests?

like image 808
Joshua Frank Avatar asked Mar 23 '13 17:03

Joshua Frank


Video Answer


3 Answers

Firstly, read this guide entirely, (if needed, twice or thrice), in order to get an idea how UIkit's touch mechanism is built. It involves what is involved in what user thinks as a touch, how events interacts with underlying hardware, what all objects intercepts it, and how you can tweak existing UIkit touch interface to your needs, at least conceptually.

Something that caught my attention that you must not miss is this too, especially properties like timestamp, phase and previousLocationInView. (I am only mentioning the ones which are not very popular).

At the end of it, I don't know, but you could end up creating your own custom gesture recognizer which would be tailor-made for your needs.

UPDATE:

Though not quite relevant to the requirement, this is good start for beginners.

like image 191
Nirav Bhatt Avatar answered Sep 28 '22 09:09

Nirav Bhatt


You should use UILongPressGestureRecognizer ( http://developer.apple.com/library/ios/#documentation/uikit/reference/UILongPressGestureRecognizer_Class/Reference/Reference.html ), and:

  • set the minimumPressDuration to something very short (e.g. 10)
  • set the allowableMovement to something very large (e.g. 500)

...now you have a gesture that is "tolerant" to wobbly-presses, etc. I have used this in several apps aimed at pre-schoolers/toddlers, and it works very well.

Re: scrolling logic, UIScrollView is easy to control programmatically - if you read the docs for UIScrollView and all the "delegate" classes you should find everything you need to "control" it through your UILongPressGestureRecognizer gesture's callback.

NB: you do NOT need to write any custom GestureRecognizer - Apples' UILongPressGestureRecognizer does all the work for you and gives you a callback when the gesture moves around; you just respond to that.

like image 21
Adam Avatar answered Sep 28 '22 09:09

Adam


There are a number of ways to customize the behavior of gesture recognition without subclassing.

A quick way that may be appropriate for some populations is to have the users configure custom gestures in Settings>General>Accessibility>AssistiveTouch. In this way, for example, a vertical pan could be recorded that can be used by tapping on the assistive touch menu, when enabled.

The rest assumes you want more control than that.

Take a look at requireGestureRecognizerToFail:. This method will allow you to prioritize the gesture recognizers, without subclassing, so that, for example, the pan gesture must fail before a tap is recognized.

The scroll view's gesture recognizers are accessible as properties on UIScrollView. You may also want to implement UIGestureRecognizerDelegate. You can adjust behavior in any of the three methods, gestureRecognizerShouldBegin:, gestureRecognizer:shouldReceiveTouch:, and gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:.

Another approach to consider is customizing the number of touches required for each gesture. Setting the minimum to two for either gesture would ensure that only the other recognizer is invoked when there is only a single touch.

For very low level control, you could subclass UIApplication or UIWindow to intercept touch delivery to the gesture recognizers.

Given the population you are targeting may not have identical capabilities, I would suggest configuring these adjustments using preferences settings, to allow them to be matched to the user. This should really be a set of global preferences set at the system level, probably in the Accessibility preferences I mentioned above, so I would encourage you to file a bug with Apple laying out exactly what adjustments are needed, and any reference information you can provide.

like image 42
Steven McGrath Avatar answered Sep 28 '22 10:09

Steven McGrath