Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any way to disable onPress on child views while swiping? #509

Open
patrik-u opened this issue Feb 4, 2022 · 3 comments
Open

Any way to disable onPress on child views while swiping? #509

patrik-u opened this issue Feb 4, 2022 · 3 comments
Labels
question Further information is requested

Comments

@patrik-u
Copy link

patrik-u commented Feb 4, 2022

I have an issue where onPress gets triggered on child views while I'm swiping in the pager view. Is there some way to prevent this from happening?

I tried tracking the pager state with the events:

                  <PagerView
                        onPageScrollStateChanged={onPageScrollStateChanged}
                        onMoveShouldSetResponderCapture={onMoveShouldSetResponderCapture}
                        onPageScroll={onPageScroll}

But it seems like the onPress is triggered before the state of the pager view updates.

    const onPageScrollStateChanged = (e) => {
        setPageScrolling(e.nativeEvent.pageScrollState != "idle");
        console.log("page scrolling", e.nativeEvent.pageScrollState != "idle");
    };
    const onMoveShouldSetResponderCapture = (e) => {
        return pageScrolling;
    };
    const onPageScroll = (e) => {
        console.log("scrolling");
        setPageScrolling(true);
    };

I'm using version 5.4.9 and Expo Go.

@patrik-u patrik-u added the question Further information is requested label Feb 4, 2022
@patrik-u
Copy link
Author

patrik-u commented Feb 4, 2022

Found a solution from this answer: satya164/react-native-tab-view#1241 (comment)

I wrapped TouchableOpacity in a new component that doesn't trigger onPress if any swipe beyond a threshold has occurred:

const TouchableOpacityFixed = ({ onPress, onPressIn, onPressOut, ...props }) => {
        const _touchActivatePositionRef = useRef(null);

        function _onPressIn(e) {
            const { pageX, pageY } = e.nativeEvent;

            _touchActivatePositionRef.current = {
                pageX,
                pageY,
            };

            onPressIn?.(e);
        }

        function _onPress(e) {
            const { pageX, pageY } = e.nativeEvent;

            const absX = Math.abs(_touchActivatePositionRef.current.pageX - pageX);
            const absY = Math.abs(_touchActivatePositionRef.current.pageY - pageY);

            const dragged = absX > 2 || absY > 2;
            if (!dragged) {
                onPress?.(e);
            }
        }

        return (
            <TouchableOpacity onPressIn={_onPressIn} onPress={_onPress} onPressOut={onPressOut} {...props}>
                {props.children}
            </TouchableOpacity>
        );
    };

And use this in my pager views, flatlists etc. to prevent onPress being triggered when swiping.

@jackblackCH
Copy link

Thank you! This is gold. This should/could be a flag on the PagerView object: something like preventEventsOnSwipe

@csulit
Copy link

csulit commented May 12, 2024

Found a solution from this answer: satya164/react-native-tab-view#1241 (comment)

I wrapped TouchableOpacity in a new component that doesn't trigger onPress if any swipe beyond a threshold has occurred:

const TouchableOpacityFixed = ({ onPress, onPressIn, onPressOut, ...props }) => {
        const _touchActivatePositionRef = useRef(null);

        function _onPressIn(e) {
            const { pageX, pageY } = e.nativeEvent;

            _touchActivatePositionRef.current = {
                pageX,
                pageY,
            };

            onPressIn?.(e);
        }

        function _onPress(e) {
            const { pageX, pageY } = e.nativeEvent;

            const absX = Math.abs(_touchActivatePositionRef.current.pageX - pageX);
            const absY = Math.abs(_touchActivatePositionRef.current.pageY - pageY);

            const dragged = absX > 2 || absY > 2;
            if (!dragged) {
                onPress?.(e);
            }
        }

        return (
            <TouchableOpacity onPressIn={_onPressIn} onPress={_onPress} onPressOut={onPressOut} {...props}>
                {props.children}
            </TouchableOpacity>
        );
    };

And use this in my pager views, flatlists etc. to prevent onPress being triggered when swiping.

Using SDK 51 not working on android.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants