Skip to content

[Slider] Fix Android hitSlop by replacing touchArea overlay with responder system#3951

Open
adids1221 wants to merge 1 commit intomasterfrom
fix/slider_android_hitslop_container_gesture
Open

[Slider] Fix Android hitSlop by replacing touchArea overlay with responder system#3951
adids1221 wants to merge 1 commit intomasterfrom
fix/slider_android_hitslop_container_gesture

Conversation

@adids1221
Copy link
Contributor

@adids1221 adids1221 commented Mar 15, 2026

Description

Fixes an Android bug where touches near the Slider thumb fail to start a drag.
The touchArea overlay (absoluteFillObject) intercepted touches in the thumb's hitSlop zone before they reached the PanResponder.

Replaced it with the container's Gesture Responder System (onStartShouldSetResponder + onResponderRelease) — the thumb (deepest child) wins for direct touches, the container handles track taps.
hitSlop now works consistently on both platforms.

Note: Incubator.Slider has the same issue but uses react-native-gesture-handler, which requires a different fix — will be addressed separately.

Changelog

Slider - Fixed Android bug where touches near the thumb failed to start a drag due to touchArea overlay intercepting hitSlop touches.

Additional info

The touchArea view (absoluteFillObject) sat between the track and thumb
in z-order, intercepting touches in the thumb's hitSlop zone on Android.
Replaced with onStartShouldSetResponder + onResponderRelease on the
container, leveraging the responder system's bubbling pattern where the
deepest child (thumb) wins for direct touches.

Made-with: Cursor
@github-actions
Copy link
Contributor

github-actions bot commented Mar 15, 2026

✅ PR Description Validation Passed

All required sections are properly filled out:

  • Description
  • Changelog
  • Additional info

Your PR is good for review! 🚀


This validation ensures all sections from the PR template are properly filled.

@adids1221
Copy link
Contributor Author

adids1221 commented Mar 15, 2026

How to reproduce

Drop this into PlaygroundScreen.tsx and test on Android:

import React, {useState} from 'react';
import {Platform} from 'react-native';
import {View, Text, Slider, Switch, Incubator} from 'react-native-ui-lib';

const TAG = `[Slider-${Platform.OS}]`;

export default function PlaygroundScreen() {
  const [disabled, setDisabled] = useState(false);

  return (
    <View flex padding-20>
      <Text text60 marginB-20>
        Slider Debug ({Platform.OS})
      </Text>

      <View row centerV marginB-20>
        <Text text70 marginR-10>
          Disabled
        </Text>
        <Switch value={disabled} onValueChange={setDisabled}/>
      </View>

      <Text text70 marginB-10>
        Slider
      </Text>
      <View
        style={{width: '100%', height: 60, justifyContent: 'center'}}
        onTouchStart={() => console.log(`${TAG} - PARENT onTouchStart`)}
        onTouchEnd={() => console.log(`${TAG} - PARENT onTouchEnd`)}
      >
        <Slider
          value={30}
          minimumValue={0}
          maximumValue={100}
          disabled={disabled}
          onSeekStart={() => console.log(`${TAG} - Slider - onSeekStart`)}
          onSeekEnd={() => console.log(`${TAG} - Slider - onSeekEnd`)}
          onValueChange={(v: number) => console.log(`${TAG} - Slider - onValueChange: ${v.toFixed(1)}`)}
        />
      </View>

      <Text text70 marginT-40 marginB-10>
        Incubator.Slider
      </Text>
      <View
        style={{width: '100%', height: 60, justifyContent: 'center'}}
        onTouchStart={() => console.log(`${TAG} - PARENT onTouchStart (Incubator)`)}
        onTouchEnd={() => console.log(`${TAG} - PARENT onTouchEnd (Incubator)`)}
      >
        <Incubator.Slider
          value={30}
          minimumValue={0}
          maximumValue={100}
          disabled={disabled}
          onSeekStart={() => console.log(`${TAG} - Incubator.Slider - onSeekStart`)}
          onSeekEnd={() => console.log(`${TAG} - Incubator.Slider - onSeekEnd`)}
          onValueChange={(v: number) => console.log(`${TAG} - Incubator.Slider - onValueChange: ${v.toFixed(1)}`)}
        />
      </View>
    </View>
  );
}

What to test

  • Android — main fix: Touch near the thumb (not exactly on it) and drag → should start dragging immediately
  • Both platforms — track tap: Tap anywhere on the track away from the thumb → value should jump to that position
  • Both platforms — normal drag: Grab the thumb and drag → should work smoothly

@adids1221 adids1221 added the hotfix Requires a hotfix release label Mar 16, 2026
@lidord-wix lidord-wix removed their request for review March 17, 2026 09:31
@lidord-wix lidord-wix removed their assignment Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hotfix Requires a hotfix release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants