Gestures¶
Native-backed gesture recognition, attached to any view-like element
via the gestures= prop. Descriptors are frozen dataclasses; their
numeric configuration crosses the bridge while callbacks are routed
through the tag-based event channel. See the
Gestures guide for usage patterns.
Native-backed gesture system.
Attach gestures to any view-like element via the gestures= prop:
import pythonnative as pn
from pythonnative import gestures
@pn.component
def Draggable():
tx = pn.use_animated_value(0.0)
ty = pn.use_animated_value(0.0)
def on_pan(event):
tx.set_value(event.translation_x)
ty.set_value(event.translation_y)
def on_end(event):
pn.Animated.spring(tx, to=0.0).start()
pn.Animated.spring(ty, to=0.0).start()
return pn.Animated.View(
pn.Text("Drag me"),
style={"transform": [{"translate_x": tx}, {"translate_y": ty}], "padding": 24},
gestures=[gestures.Pan(on_change=on_pan, on_end=on_end)],
)
Each gesture descriptor is a frozen dataclass holding numeric configuration plus user callbacks. The reconciler serializes the configuration into plain dicts for the native handler (so prop diffing never compares closures) and routes the callbacks through the tag-based event channel. Recognition itself is native:
- iOS attaches real
UIGestureRecognizerinstances. - Android feeds raw
MotionEventstreams into the pure-PythonGestureArbiterbelow. - Desktop feeds Tk pointer events into the same arbiter.
All gestures attached to one view recognize simultaneously; there is no cross-gesture exclusivity arbitration yet.
Every callback receives a GestureEvent
with position, translation, velocity, scale, and rotation populated as
appropriate for the gesture kind.
Classes:
| Name | Description |
|---|---|
GestureState |
States reported on |
GestureEvent |
Snapshot delivered to gesture callbacks. |
Tap |
Recognize |
LongPress |
Recognize a sustained press. |
Pan |
Track a drag with translation and velocity. |
Swipe |
Recognize a quick directional flick. |
Pinch |
Track a two-finger pinch; |
Rotation |
Track a two-finger rotation; |
GestureArbiter |
Turn a raw pointer-event stream into gesture event payloads. |
Functions:
| Name | Description |
|---|---|
serialize_gestures |
Split gesture descriptors into native config dicts and event routers. |
GestureStateName
module-attribute
¶
GestureStateName = Literal['began', 'changed', 'ended', 'cancelled']
GestureSpec
module-attribute
¶
Any gesture descriptor accepted by the gestures= prop.
EmitFn
module-attribute
¶
emit(gesture_index, payload): the arbiter's output channel.
GestureState
¶
States reported on GestureEvent.state.
Attributes:
| Name | Type | Description |
|---|---|---|
BEGAN |
|
|
CHANGED |
|
|
ENDED |
|
|
CANCELLED |
|
GestureEvent
dataclass
¶
GestureEvent(kind: str, state: GestureStateName, x: float = 0.0, y: float = 0.0, translation_x: float = 0.0, translation_y: float = 0.0, velocity_x: float = 0.0, velocity_y: float = 0.0, scale: float = 1.0, rotation: float = 0.0, pointer_count: int = 1, direction: Optional[str] = None)
Snapshot delivered to gesture callbacks.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
str
|
Gesture kind ( |
state |
GestureStateName
|
One of |
x |
float
|
Pointer x-position in the view's coordinate space (points). |
y |
float
|
Pointer y-position in the view's coordinate space (points). |
translation_x |
float
|
Horizontal displacement since the gesture activated (pan only). |
translation_y |
float
|
Vertical displacement since the gesture activated (pan only). |
velocity_x |
float
|
Horizontal pointer velocity in points/second (pan and swipe). |
velocity_y |
float
|
Vertical pointer velocity in points/second (pan and swipe). |
scale |
float
|
Pinch scale factor relative to activation (pinch only). |
rotation |
float
|
Rotation in radians relative to activation (rotation only). |
pointer_count |
int
|
Number of pointers currently down. |
direction |
Optional[str]
|
Resolved swipe direction (swipe only). |
Tap
dataclass
¶
Tap(on_begin: Optional[GestureCallback] = None, on_change: Optional[GestureCallback] = None, on_end: Optional[GestureCallback] = None, kind: str = 'tap', on_tap: Optional[GestureCallback] = None, n_taps: int = 1, max_distance: float = 12.0)
Bases: _BaseGesture
Recognize n_taps quick taps.
Attributes:
| Name | Type | Description |
|---|---|---|
on_tap |
Optional[GestureCallback]
|
Called once the tap (or multi-tap) completes. |
n_taps |
int
|
Number of consecutive taps required ( |
max_distance |
float
|
Maximum pointer travel (points) for a touch to still count as a tap. |
LongPress
dataclass
¶
LongPress(on_begin: Optional[GestureCallback] = None, on_change: Optional[GestureCallback] = None, on_end: Optional[GestureCallback] = None, kind: str = 'long_press', on_long_press: Optional[GestureCallback] = None, min_duration_ms: float = 500.0, max_distance: float = 12.0)
Bases: _BaseGesture
Recognize a sustained press.
on_long_press fires as soon as the press has been held for
min_duration_ms (matching UILongPressGestureRecognizer);
on_end fires when the finger lifts.
Attributes:
| Name | Type | Description |
|---|---|---|
on_long_press |
Optional[GestureCallback]
|
Called at activation time. |
min_duration_ms |
float
|
Hold duration required to activate. |
max_distance |
float
|
Maximum pointer travel before the press fails. |
Pan
dataclass
¶
Pan(on_begin: Optional[GestureCallback] = None, on_change: Optional[GestureCallback] = None, on_end: Optional[GestureCallback] = None, kind: str = 'pan', min_distance: float = 10.0, min_pointers: int = 1)
Bases: _BaseGesture
Track a drag with translation and velocity.
Activates once the pointer travels min_distance points, then
reports on_change for every movement with translation measured
from the activation point, and on_end with release velocity.
Attributes:
| Name | Type | Description |
|---|---|---|
min_distance |
float
|
Travel (points) required before the pan activates. |
min_pointers |
int
|
Minimum pointers that must be down. |
Swipe
dataclass
¶
Swipe(on_begin: Optional[GestureCallback] = None, on_change: Optional[GestureCallback] = None, on_end: Optional[GestureCallback] = None, kind: str = 'swipe', on_swipe: Optional[GestureCallback] = None, direction: SwipeDirection = 'any', min_velocity: float = 300.0)
Bases: _BaseGesture
Recognize a quick directional flick.
Attributes:
| Name | Type | Description |
|---|---|---|
on_swipe |
Optional[GestureCallback]
|
Called once on release with the resolved
|
direction |
SwipeDirection
|
Required direction, or |
min_velocity |
float
|
Minimum release speed in points/second. |
Pinch
dataclass
¶
Pinch(on_begin: Optional[GestureCallback] = None, on_change: Optional[GestureCallback] = None, on_end: Optional[GestureCallback] = None, kind: str = 'pinch')
Rotation
dataclass
¶
Rotation(on_begin: Optional[GestureCallback] = None, on_change: Optional[GestureCallback] = None, on_end: Optional[GestureCallback] = None, kind: str = 'rotation')
GestureArbiter
¶
Turn a raw pointer-event stream into gesture event payloads.
One arbiter serves one view. The host backend feeds it normalized
pointer events (positions in the view's coordinate space, times in
seconds, any monotonic clock) and provides an emit callback
that forwards (gesture_index, payload) pairs to
dispatch_event.
Long-press needs a timer: after each pointer event, hosts should
check next_deadline
and schedule a poll
call for that time.
Methods:
| Name | Description |
|---|---|
pointer_down |
Record a pointer press and advance every recognizer. |
pointer_move |
Record pointer travel and advance every recognizer. |
pointer_up |
Record a pointer release and advance every recognizer. |
cancel |
Abort every in-flight gesture (e.g. touch stolen by a scroll parent). |
poll |
Advance time-based recognizers (long-press activation). |
next_deadline |
Earliest time |
has_active_pan |
Whether a pan gesture is currently activated. |
pointer_down
¶
Record a pointer press and advance every recognizer.
pointer_move
¶
Record pointer travel and advance every recognizer.
pointer_up
¶
Record a pointer release and advance every recognizer.
event_from_payload
¶
event_from_payload(payload: Dict[str, Any]) -> GestureEvent
Build a GestureEvent from a payload dict.
Unknown keys are dropped so platform handlers can attach extra diagnostics without breaking the public dataclass.
serialize_gestures
¶
serialize_gestures(specs: Sequence[Any]) -> Tuple[List[Dict[str, Any]], Dict[str, Callable[..., Any]]]
Split gesture descriptors into native config dicts and event routers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
specs
|
Sequence[Any]
|
The value of an element's |
required |
Returns:
| Type | Description |
|---|---|
List[Dict[str, Any]]
|
|
Dict[str, Callable[..., Any]]
|
JSON-ish config dicts (one per gesture, in order) and |
Tuple[List[Dict[str, Any]], Dict[str, Callable[..., Any]]]
|
|
Tuple[List[Dict[str, Any]], Dict[str, Callable[..., Any]]]
|
native payload into a |
Tuple[List[Dict[str, Any]], Dict[str, Callable[..., Any]]]
|
user callback. |
make_arbiter
¶
Build a GestureArbiter from serialized specs.
See also¶
- The Gestures guide walks through taps, drags, and gesture-driven animations.
- Animated pairs with
Panvelocity for springs and decays.