-
-
Save mrzmyr/9ac94ca4622c1602a2a3 to your computer and use it in GitHub Desktop.
var Index = React.createClass({ | |
getInitialState: function () { | |
return { | |
lastPress: 0 | |
} | |
}, | |
onPress: function () { | |
var delta = new Date().getTime() - this.state.lastPress; | |
if(delta < 200) { | |
// double tap happend | |
} | |
this.setState({ | |
lastPress: new Date().getTime() | |
}) | |
}, | |
render: function() { | |
return ( | |
<TouchableHighlight onPress={this.onPress}></TouchableHighlight> | |
) | |
} | |
}); |
setState is asynchronous method, so it's better to use "this", not "state".
onDoublePress = (date) => {
const time = new Date().getTime();
const delta = time - this.lastPress;
const DOUBLE_PRESS_DELAY = 400;
if (delta < DOUBLE_PRESS_DELAY) {
// Success double press
}
this.lastPress = time;
};
Agree with @iksent. The issue with using state is it'll trigger a re-render, which in a complicated view it's not going to be efficient.
Thanks for the snippet.
Thanks!
try this new component:
A Component for Double Click based on TouchableOpacity Wrapper.
https://www.npmjs.com/package/rn-double-click
👍 Thanks !
Hey this is really smart. Thanks!
How to prevent the single tap action though ? :( setTimeout is really unreliable in RN it seems
Edit: nevermind, its only in debug setTimeout does not behave
thank for the snippet
From this post, I came up with this, and it works great.
const MultiTapOverlay: () => ReactNode = ({
onLongPress,
onMultiTaps,
multiTapCount = 4,
multiTapDelay = 300,
children
}) => {
const [lastPress, setLastPress] = useState(null);
const [tapCount, setTapCount] = useState(0);
const handlePress = () => {
const now = Date.now();
setLastPress(now);
if (now - lastPress <= multiTapDelay) {
if (tapCount < multiTapCount - 1) {
setTapCount(tapCount + 1);
} else {
setTapCount(0);
onMultiTaps && onMultiTaps();
}
} else {
setTapCount(1);
}
};
const handleLongPress = () => onLongPress && onLongPress();
return (
<TouchableOpacity
delayLongPress={ 1000 }
activeOpacity={ 0.8 }
onLongPress={ handleLongPress }
onPress={ handlePress }
>
{ children }
</TouchableOpacity>
);
};
any one have idea how to handle tripple and quadrupple taps like in youtube app?
@arfa123 have a look at my MultiTapOverlay
component, just above your comment; does it work for you? Or do you need a component that will tell you how many taps was pressed (e.g. single, double triple, etc.), handling not only one case but many cases?
@yanickrochon did u read @iksent comment?
@fukemy I'm not certain what you mean, of course I have read @iksent 's comment. Back in 2020, React hooks were relatively new. So, if I would rewrite the code I posted, it would more look like this one, today :
const MultiPressOverlay: () => ReactNode = ({
delayLongPress = 1000,
delayMultiPress = 300,
minMultiPress = 4,
onPress,
onLongPress,
onMultiPress,
children
}) => {
const [lastPress, setLastPress] = useState(null);
const [pressCount, setPressCount] = useState(0);
useEffect(() => {
if ((pressCount > 1) && (pressCount >= minMultiPress)) {
setPressCount(0);
onMultiPress && onMultiPress(new CustomEvent("multipress", { detail: { pressCount } }));
}
}, [pressCount, minMultiPress, onMultiPress]);
const handlePress = evt => {
const now = Date.now();
setLastPress(now);
if (now - lastPress <= delayMultiPress) {
setPressCount(pressCount => pressCount + 1);
} else {
setPressCount(1);
}
onPress && onPress(evt);
};
return (
<TouchableOpacity
delayLongPress={ delayLongPress }
activeOpacity={ 0.8 }
onLongPress={ onLongPress }
onPress={ handlePress }
>
{ children }
</TouchableOpacity>
);
};
NOTE: There is still a lot of room for improvement, but this was written without tests whatsoever. I would move the onPress
inside the useEffect
callback, with a timer, to trigger a single press event is the delayMultiPress
is expired and less than minMultiPress
has beeen triggered, etc.
Thanks for this!