Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
[Share code] Gestures for Pythonista
-
This is a convenience class for enabling gestures in Pythonista ui applications, including built-in views. Main intent here has been to make them Python friendly, hiding all the Objective-C stuff.
Get it from GitHub.
For example, do something when user swipes left on a TextView:
def swipe_handler(view, swipe_start_location): print ‘I was swiped, starting from ‘ + str(swipe_start_location) tv = ui.TextView() gestures = Gestures() gestures.add_swipe(tv, swipe_handler, direction = Gestures.LEFT)
These gestures and methods are provided:
*
add_tap(view, action, number_of_taps_required, number_of_touches_required)
add_long_press(view, action, number_of_taps_required, number_of_touches_required, minimum_press_duration, allowable_movement)
add_pan(view, action, minimum_number_of_touches, maximum_number_of_touches, set_translation)
add_screen_edge_pan(view, action, edges)
(see below for possibleedges
values)add_pinch(view, action)
add_rotation(view, action)
add_swipe(view, action, direction, number_of_touches_required)
(see below for possibledirection
values)
In all cases, only the
view
andaction
(event handler function like theswipe_handler
in the example) are required. Refer to the UIKit UIGestureRecognizer documentation on usage and default values.Corresponding handler signatures are (representative names only, use whatever is convenient for you):
tap(view, location)
- same for long presses and swipes (where the location is the where the swipe began)pan(view, location, absolute_translation, velocity)
- same for pans from the screen edgespinch(view, location, scale, velocity)
rotation(view, location, rotation, velocity)
scale
,rotation
andvelocity
are numbers.location
andvelocity
values areui.Point
instances withx
andy
members.Possible screen edge pan
edges
values are (only one of these):Gestures.EDGE_NONE
,Gestures.EDGE_TOP
,Gestures.EDGE_LEFT
,Gestures.EDGE_BOTTOM
,Gestures.EDGE_RIGHT
,Gestures.EDGE_ALL
Possible swipe
direction
values are (one or a list of these; if you need to know the actual swipe direction, add different directions as separate gestures):Gestures.RIGHT
,Gestures.LEFT
,Gestures.UP
,Gestures.DOWN
All of the
add_x
methods return arecognizer
object that can be used to remove or disable the gesture as needed:remove(view, recognizer)
disable(recognizer)
enable(recognizer)
You can also remove all gestures from a view with
remove_all_gestures(view)
.NOTES:
- To bridge the Objective-C and Pyyhon worlds, all the gestures depend on the Gestures instance used to create them being live, so retain the reference to it or Pythonista will crash when the gesture is detected.
- Single Gestures instance can be used to add any number of gestures to any number of views.
- If you need to create a lot of dynamic gestures in a long-running, make sure to explicitly
remove
them when no longer needed, to avoid a memory leak.
-
@JonB strikes again! On his advice, Gestures now uses retain_global for added robustness and ease of use. Here are the updated notes from the readme:
- To facilitate the gesture handler callbacks from Objective-C to Python, the Gestures instance used to create the gesture must be live. You do not need to manage that as objc_util.retain_global is used to keep a global reference around. If you for some reason must track the reference manually, you can turn this behavior off with a
retain_global_reference=False
parameter for the constructor. - Single Gestures instance can be used to add any number of gestures to any number of views, but you can just as well create a new instance whenever and wherever you need to add a new handler -
Gestures().add_swipe(...)
. - If you need to create millions of dynamic gestures in a long-running app, it can be worthwhile to explicitly
remove
them when no longer needed, to avoid a memory leak.
- To facilitate the gesture handler callbacks from Objective-C to Python, the Gestures instance used to create the gesture must be live. You do not need to manage that as objc_util.retain_global is used to keep a global reference around. If you for some reason must track the reference manually, you can turn this behavior off with a
-
As discussed in another thread, added on_main_thread for additional thread safety. Probably worth downloading again if you are using this.
-
I’m getting an error. “No method found for selector addGestureRecognizer”
-
@robertiii, I could not immediately replicate the error.
Could you please share the snippet of your code where you are using Gestures and, just to be sure that the file has not been corrupted somehow, some lines around the line in Gestures.py that are giving you the error?