Open AlexDiMaria opened 1 year ago
import {Button} from "react-native-paper"; import TinderCard from "react-tinder-card"; <TinderCard className="pressable"> <Button onPress={() => { console.log("Ciao") }} > <Text> Ciao </Text> </Button> </TinderCard>
I'm trying to create a button inside a card with this simple snippet code on React Native.
When I do test with an iOS emulator all it's working fine, but on Android the onPress event is not recognize... What i've to do?
I have the same problem. Have you found a solution?
Got the same issue, has anybody solved it yet?
Hey guys I've figured it out! Here is the code, this is the exact same thing as the TinderCard (code is literally stolen form this repo) but I've made a small change. You can now pass a function to the TinderCard component called onPress that is executed when you click on a card
import React from 'react'; import {View, PanResponder, Dimensions} from 'react-native'; import {useSpring, animated} from '@react-spring/native'; const {height, width} = Dimensions.get('window');
const settings = { maxTilt: 25, // in deg rotationPower: 50, swipeThreshold: 1, // need to update this threshold for RN (1.5 seems reasonable...?) };
// physical properties of the spring const physics = { touchResponsive: { friction: 50, tension: 2000, }, animateOut: { friction: 30, tension: 400, }, animateBack: { friction: 10, tension: 200, }, };
let gestureGlobal;
const pythagoras = (x, y) => { return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); };
const animateOut = async (gesture, setSpringTarget) => { const diagonal = pythagoras(height, width); const velocity = pythagoras(gesture.vx, gesture.vy); const finalX = diagonal gesture.vx; const finalY = diagonal gesture.vy; const finalRotation = gesture.vx * 45; const duration = diagonal / velocity;
setSpringTarget({ x: finalX, y: finalY, rot: finalRotation, // set final rotation value based on gesture.vx config: {duration: duration}, });
// for now animate back return await new Promise(resolve => setTimeout(() => { resolve(); }, duration), ); };
const animateBack = setSpringTarget => { // translate back to the initial position setSpringTarget({x: 0, y: 0, rot: 0, config: physics.animateBack}); };
const getSwipeDirection = speed => { if (Math.abs(speed.x) > Math.abs(speed.y)) { return speed.x > 0 ? 'right' : 'left'; } else { return speed.y > 0 ? 'down' : 'up'; } };
// must be created outside of the TinderCard forwardRef const AnimatedView = animated(View);
const TinderCard = React.forwardRef( ( { flickOnSwipe = true, children, onSwipe, onCardLeftScreen, className, onPress, preventSwipe = [], }, ref, ) => { const [{x, y, rot}, setSpringTarget] = useSpring(() => ({ x: 0, y: 0, rot: 0, config: physics.touchResponsive, }));
React.useImperativeHandle(ref, () => ({
async swipe(dir = 'right') {
if (onSwipe) onSwipe(dir);
const power = 1.3;
const disturbance = (Math.random() - 0.5) / 2;
if (dir === 'right') {
await animateOut({vx: power, vy: disturbance}, setSpringTarget);
} else if (dir === 'left') {
await animateOut({vx: -power, vy: disturbance}, setSpringTarget);
} else if (dir === 'up') {
await animateOut({vx: disturbance, vy: power}, setSpringTarget);
} else if (dir === 'down') {
await animateOut({vx: disturbance, vy: -power}, setSpringTarget);
}
if (onCardLeftScreen) onCardLeftScreen(dir);
},
}));
const handleSwipeReleased = React.useCallback(
async (setSpringTarget, gesture) => {
// Check if this is a swipe
if (
Math.abs(gesture.vx) > settings.swipeThreshold ||
Math.abs(gesture.vy) > settings.swipeThreshold
) {
const dir = getSwipeDirection({x: gesture.vx, y: gesture.vy});
if (flickOnSwipe) {
if (!preventSwipe.includes(dir)) {
if (onSwipe) onSwipe(dir);
await animateOut(gesture, setSpringTarget);
if (onCardLeftScreen) onCardLeftScreen(dir);
return;
}
}
}
gestureGlobal = gesture;
// Card was not flicked away, animate back to start
animateBack(setSpringTarget);
},
[flickOnSwipe, onSwipe, onCardLeftScreen, preventSwipe],
);
const panResponder = React.useMemo(
() =>
PanResponder.create({
// Ask to be the responder:
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
// The gesture has started.
// Probably wont need this anymore as postion i relative to swipe!
setSpringTarget({
x: gestureState.dx,
y: gestureState.dy,
rot: 0,
config: physics.touchResponsive,
});
},
onPanResponderMove: (evt, gestureState) => {
// use guestureState.vx / guestureState.vy for velocity calculations
// translate element
let rot = ((300 * gestureState.vx) / width) * 15; // Magic number 300 different on different devices? Run on physical device!
rot = Math.max(Math.min(rot, settings.maxTilt), -settings.maxTilt);
setSpringTarget({
x: gestureState.dx,
y: gestureState.dy,
rot,
config: physics.touchResponsive,
});
},
onPanResponderTerminationRequest: (evt, gestureState) => {
return true;
},
onPanResponderRelease: (evt, gestureState) => {
// The user has released all touches while this view is the
// responder. This typically means a gesture has succeeded
// enable
handleSwipeReleased(setSpringTarget, gestureState);
if (Math.abs(gestureGlobal.vx) <= 0.005) {
onPress();
}
},
}),
[],
);
return (
<AnimatedView
{...panResponder.panHandlers}
style={{
transform: [
{translateX: x},
{translateY: y},
{rotate: rot.interpolate(rot => `${rot}deg`)},
],
}}>
{children}
</AnimatedView>
);
}, );
// module.exports = TinderCard export default TinderCard;
I'm trying to create a button inside a card with this simple snippet code on React Native.
When I do test with an iOS emulator all it's working fine, but on Android the onPress event is not recognize... What i've to do?