Motion Event Behaviors
The MotionCollideBehavior and
MotionBlockBehavior
mixin classes provide generic
motion event filtering for any motion event type (hover, drag, custom events).
These behaviors are commonly used with HoverBehavior
but are designed to be generic and reusable with any motion event system.
For an overview of behaviors, please refer to the behaviors
documentation.
Components
- MotionCollideBehavior:
Filters motion events to only process those within widget bounds or grabbed.
Essential for RecycleView and
ScrollView to prevent conflicts outside
visible area.
- MotionBlockBehavior:
Blocks unregistered motion events from passing through widget bounds.
Makes widgets “opaque” to motion events, preventing leak-through to
background widgets.
Examples
Using MotionCollideBehavior with HoverBehavior:
from kivy.uix.scrollview import ScrollView
from kivy.uix.label import Label
from kivy.uix.behaviors.hover import HoverBehavior
from kivy.uix.behaviors.motion import MotionCollideBehavior
class HoverScrollView(MotionCollideBehavior, ScrollView):
# Filters hover events outside stencil bounds
pass
class HoverItem(HoverBehavior, MotionCollideBehavior, Label):
def on_enter(self):
self.color = [1, 0, 0, 1] # Red on hover
def on_leave(self):
self.color = [1, 1, 1, 1] # White normally
Using MotionBlockBehavior to prevent event leak-through:
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from motion_behaviors import MotionBlockBehavior
class OpaqueButton(MotionBlockBehavior, Button):
# Blocks unregistered motion events from passing through
pass
layout = FloatLayout()
layout.add_widget(HoverScrollView()) # Background
layout.add_widget(OpaqueButton()) # Foreground
# Hovering over button won't trigger ScrollView hover
Important Notes
DO NOT use MotionCollideBehavior and
MotionBlockBehavior together on the same
widget. They serve different purposes:
- MotionCollideBehavior: Filters events outside widget bounds
-
- MotionBlockBehavior: Blocks unregistered event types from passing through
Use for: Overlay widgets, modal dialogs, foreground elements
Purpose: Prevent events from leaking to widgets behind
Combining them creates redundant or conflicting logic.
See MotionCollideBehavior and
MotionBlockBehavior for details.
-
class kivy.uix.behaviors.motion.MotionBlockBehavior[source]
Bases: builtins.object
Mixin to block unregistered motion events from passing through.
Makes widgets “opaque” to motion events they haven’t registered to handle.
When a motion event collides with the widget but the widget hasn’t
registered for that event type, the event is blocked from propagating to
widgets behind it.
Generic Design
Works with ANY motion event type (hover, drag, custom events). Prevents
motion events from “leaking through” foreground widgets to background
widgets.
Comparison with HoverBehavior
For hover-specific blocking with more control, consider using
HoverBehavior with hover_mode=’self’
instead.
Technical Note
The collision check uses widget.collide_point(*motion_event.pos)().
For custom collision shapes, override collide_point() in your
widget.
Grabbed Events
Grabbed events always pass through, even if not registered. This ensures
proper event lifecycle - if a widget grabs an event, it must receive all
subsequent updates and the end event.
-
on_motion(event_type: str, motion_event) → bool[source]
Block unregistered motion events that collide with widget.
Processing logic:
If grabbed by this widget -> pass to super() (process)
If collides but NOT registered -> return True (block)
Otherwise -> pass to super() (continue propagation)
- Parameters:
event_type – Motion event type (“begin”, “update”, “end”)
motion_event – MotionEvent to potentially block
- Returns:
True if event was blocked or handled, False otherwise
-
class kivy.uix.behaviors.motion.MotionCollideBehavior[source]
Bases: builtins.object
Mixin to filter motion events based on collision detection.
This mixin overrides on_motion() to only process events that either:
Collide with the widget’s bounds, OR
Are grabbed events (motion_event.grab_current is self)
Generic Design
Works with ANY motion event type (hover, drag, custom events).
Commonly used with HoverBehavior but
not limited to hover events.
Primary Use Case - StencilView
Essential for widgets that use stencil clipping
(RecycleView,
ScrollView). Without this mixin, widgets
outside the stencil bounds can still receive motion events, leading to
confusing behavior where invisible items respond.
Technical Note
The collision check uses widget.collide_point(*motion_event.pos)(),
which tests against the widget’s bounding box. For complex shapes, override
collide_point() in your widget class for custom collision logic.
Grabbed Events
Grabbed events always pass through, even if they don’t collide. This ensures
proper event completion - if a widget grabbed an event (e.g., on hover
enter), it must receive the end event even if the cursor moved outside
bounds.
-
on_motion(event_type: str, motion_event) → bool[source]
Filter motion events by collision or grab status.
Only processes events that:
- Parameters:
event_type – Motion event type (“begin”, “update”, “end”)
motion_event – MotionEvent to potentially filter
- Returns:
Result of super().on_motion() if passed filter, False otherwise