How to undo react-native-gesture-handler

560 views Asked by At

I'm using react-native-reanimated v 1.9 together with react-native-gesture-handler to drag an element on the screen, I need to be able to reset the element to the previous position after the user press the "UNDO" button.

After Initializing some animated values:

this.X = new Value();
this.Y = new Value();
const offsetX = new Value();
const offsetY = new Value();

....this.handlePan function get the pan events from here:

 <PanGestureHandler
          ref={this.panRef}
          enabled={this.panGestureHandlerEnabler}
          onGestureEvent={this.handlePan}
          onHandlerStateChange={this.handlePan}>
          <Animated.View>
            .......
          </Animated.View>
  </PanGestureHandler>

from this.handlePan the events are mapped to x and y, I can then use the react-native-reanimated call() method to extract some animated values at the end of any pan movement and make them available for the function recordNewState():

 this.handlePan = event([
      {
        nativeEvent: ({
          translationX: x,
          translationY: y,
          absoluteY: Y,
          absoluteX: X,
          state,
        }) =>
          block([
            set(this.X, add(x, offsetX)), 
            set(this.Y, add(y, offsetY)),
            cond(eq(state, State.END), [
              set(offsetX, add(offsetX, x)),
              set(offsetY, add(offsetY, y)),
              call([this.X, this.Y], (finalXY) => {
              recordNewState({
              action: 'XY',
              value: {X: x, Y: y},
            });
           }),                
          ]),
        ]),
      },
      {useNativeDriver: true},
    ]);

The function recordNewState() basically build up an array of animated values, that are made available for the undo() function:

this.undo = () => {
  if (lastRecordedState.length > 1) {
    const undoAction = 
     lastRecordedState[lastRecordedState.length - 1];
    switch (undoAction.action) {
      case 'XY':
        block([
          offsetX.setValue(sub(offsetX, undoAction.value.X)),
          offsetY.setValue(sub(offsetY, undoAction.value.Y)),
        ]);
        break;
      default:
        break;
    }
  }
};

Here I check for the latest animated value (undoAction.action), in the switch statement, if it's an XY I translate the item subtracting the latest animated values. With

   block([
          offsetX.setValue(sub(offsetX, undoAction.value.X)),
          offsetY.setValue(sub(offsetY, undoAction.value.Y)),
        ]);

the item doesn't move back to the previous position and the call() method get called again adding another animated value to the array.

0

There are 0 answers