-
Notifications
You must be signed in to change notification settings - Fork 617
Description
Overview
Add scroll wheel support to SkiaSharp's Android MAUI views by handling ACTION_SCROLL events in SKTouchHandler and normalizing AXIS_VSCROLL values to the v120 standard (120 = one discrete mouse wheel notch).
Parent issue: #3533
Current State
The Android SKTouchHandler (source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Core/Platform/Android/SKTouchHandler.cs) currently:
- Handles:
MotionEventActions.Down,Move,Up,PointerDown,PointerUp,Cancel - Does NOT handle:
ACTION_SCROLL - All
SKTouchEventArgsare constructed withwheelDelta = 0
Platform Details
Native API
MotionEvent with ACTION_SCROLL:
"The motion event contains relative vertical and/or horizontal scroll offsets."
— MotionEvent.ACTION_SCROLL
// Received via onGenericMotionEvent(), NOT onTouchEvent()
float vScroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
float hScroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);Note:
ACTION_SCROLLevents are delivered throughonGenericMotionEvent(), notonTouchEvent(). This is a separate event path from touch/pointer events. Pointer movement usesACTION_MOVE(notACTION_POINTER_MOVE, which is not a standard public constant).
Raw Values Per Discrete Mouse Notch
| Device | AXIS_VSCROLL value | Notes |
|---|---|---|
| Standard mouse wheel | ±1.0 | One notch = typically ±1.0 |
| High-res trackpad | ±0.1 to ±0.5 | Fractional, device-dependent |
| Fast scroll | ±1.0 per event | Multiple rapid events |
⚠️ Note: The±1.0value per mouse notch is the empirically observed default across standard mice and Android devices. The Android documentation does not explicitly guarantee this value — it describesAXIS_VSCROLLas a "relative vertical scroll offset" without specifying units per notch. The×120normalization assumes this de-facto standard. If a device produces different values, the normalization will be proportionally off.
Sign Convention
"Positive values indicate scrolling forward (away from the user)"
— MotionEvent.AXIS_VSCROLL
AXIS_VSCROLL > 0= scroll up (away from user)AXIS_VSCROLL < 0= scroll down (toward user)- Already matches v120 sign convention — no negation needed
Official Documentation
- MotionEvent class reference — full class with all action types and axes
- MotionEvent.AXIS_VSCROLL — vertical scroll offset, "positive values indicate scrolling forward (away from the user)"
- MotionEvent.AXIS_HSCROLL — horizontal equivalent
- MotionEvent.ACTION_SCROLL — "the motion event contains relative vertical and/or horizontal scroll offsets"
- View.onGenericMotionEvent — the event handler that receives scroll events
Normalization Logic
// In SKTouchHandler.cs, handle ACTION_SCROLL:
float axisValue = motionEvent.GetAxisValue(Axis.Vscroll);
int wheelDelta = (int)Math.Round(axisValue * 120.0);
// Mouse notch (1.0) → 120
// Trackpad micro (0.1) → 12
// Trackpad half (0.5) → 60Expected Results
| Input | Calculation | WheelDelta |
|---|---|---|
| Mouse notch up (1.0) | round(1.0 × 120) |
120 |
| Mouse notch down (-1.0) | round(-1.0 × 120) |
-120 |
| Trackpad micro up (0.1) | round(0.1 × 120) |
12 |
| Trackpad half down (-0.5) | round(-0.5 × 120) |
-60 |
Implementation Notes
ACTION_SCROLLevents come throughOnGenericMotionEvent(), notOnTouchEvent(). You may need to register a generic motion listener or override the view'sOnGenericMotionEvent.- The MAUI Android handler is in
source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Core/Platform/Android/SKTouchHandler.cs - Fire
SKTouchAction.WheelChangedwithSKTouchDeviceType.Mouse - Use
motionEvent.GetX()/motionEvent.GetY()for pointer location - Set
inContact = false(wheel doesn't imply contact) - Feed
args.Handledback to return value ofOnGenericMotionEvent(return true to consume) - Reference: Windows handler in
Platform/Windows/SKTouchHandler.cslines 101-104, 122-124 for pattern
Metadata
Metadata
Assignees
Labels
Type
Projects
Status