I made some code based on your lecture.
When onPanResponderRelease is executed, if dx<-50, goLeft.start() is used to move toValue: -200.
I also refreshed the position using position.flattenOffset(); In onPanResponderGrant, I saved the position value using setOffset.
However, when goLeft.start() is executed and the tovalue has shifted by -200 and the card is touched again, onPanResponderGrant starts at -200 but ,the position is set to -400 and the card starts at an entirely different position.
How can I fix the code so that after goLeft.start() is executed, the touch will start at -200?
this is my code
import React, { useRef, useState } from "react";
import { Animated, PanResponder, Text, View } from "react-native";
import styled from "styled-components/native";
import { Ionicons } from "@expo/vector-icons";
import icons from "./icons";
const Container = styled.View`
flex: 1;
justify-content: center;
align-items: center;
background-color: #00a8ff;
`;
const Card = styled(Animated.createAnimatedComponent(View))`
background-color: white;
width: 100px;
height: 100px;
justify-content: center;
align-items: center;
border-radius: 12px;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2);
position: absolute;
`;
const Btn = styled.TouchableOpacity`
margin: 0px 10px;
`;
const BtnContainer = styled.View`
flex-direction: row;
flex: 1;
`;
const CardContainer = styled.View`
flex: 3;
justify-content: center;
align-items: center;
`;
export default function App() {
const [left, setLeft] = useState(false);
// Values
const position = useRef(new Animated.Value(0)).current;
// Animations
const goCenter = Animated.spring(position, {
toValue: 0,
useNativeDriver: true,
});
const goLeft = Animated.spring(position, {
toValue: -200,
tension: 5,
useNativeDriver: true,
restDisplacementThreshold: 100,
restSpeedThreshold: 100,
});
const goRight = Animated.spring(position, {
toValue: 500,
tension: 5,
useNativeDriver: true,
});
// Pan Responders
const panResponder = useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderGrant: () => {
console.log("Grant", position._value);
position.setOffset(position._value);
position.flattenOffset();
// position.addListener(() => {});
},
onPanResponderMove: (_, { dx }) => {
console.log("Move:", dx);
position.addListener(() => {});
position.setValue(dx);
// position.addListener(() => {});
},
onPanResponderRelease: (_, { dx }) => {
console.log("Release:", dx);
if (dx < -30) {
console.log("!!!");
goLeft.start();
position.flattenOffset();
} else {
position.flattenOffset();
}
},
})
).current;
position.addListener(() => console.log("p:", position));
// State
const [index, setIndex] = useState(0);
const onDismiss = () => {
// position.setValue(-100);
// Animated.timing(position, { toValue: -60, useNativeDriver: true }).start();
};
const closePress = () => {
console.log("222");
goLeft.start(onDismiss);
};
const checkPress = () => {
console.log("111");
goRight.start(onDismiss);
};
return (
<Container>
<CardContainer>
<Card
{...panResponder.panHandlers}
style={{
transform: [{ translateX: position }],
}}
>
<Ionicons color="#192a56" size={98} />
</Card>
</CardContainer>
<BtnContainer>
<Btn onPress={closePress}>
<Ionicons name="close-circle" color="white" size={58} />
</Btn>
<Btn onPress={checkPress}>
<Ionicons name="checkmark-circle" color="white" size={58} />
</Btn>
</BtnContainer>
</Container>
);
}