Gestures and Reanimated

Back

Loading concept...

🎮 Animation Magic: Gestures & Reanimated in React Native

Imagine your phone screen is a magic sandbox. When you touch it, poke it, swipe it, or pinch it—things happen! That’s what we’re learning today: how to make your app feel alive by responding to your fingers like magic.


🧙‍♂️ The Story of Two Best Friends

Meet Gesture Handler and Reanimated. They’re best friends who work together to create smooth, buttery animations in your app.

  • Gesture Handler is like a super-sensitive detective 🔍 who watches your fingers and says, “Hey! The user just tapped here!” or “Look! They’re swiping left!”

  • Reanimated is like a magical artist 🎨 who takes that information and makes things move beautifully on screen—no stuttering, no lag, just smooth motion.

Together, they make your app feel like a living, breathing thing.


🔧 1. Gesture Handler Setup

What Is It?

Before we can detect finger touches, we need to install our detective! Gesture Handler needs to be set up properly so it can watch for all those taps, swipes, and pinches.

Simple Analogy

Think of it like setting up a security camera before you can see what’s happening in your house. No camera = no watching!

How to Set It Up

Step 1: Install the package

npm install react-native-gesture-handler

Step 2: Wrap your whole app with the magic wrapper

import { GestureHandlerRootView }
  from 'react-native-gesture-handler';

export default function App() {
  return (
    <GestureHandlerRootView
      style={{ flex: 1 }}>
      {/* Your app goes here */}
    </GestureHandlerRootView>
  );
}

💡 Why This Matters

Without GestureHandlerRootView, gestures won’t work! It’s like trying to listen to music without speakers—nothing happens.

graph TD A["Your App"] --> B["GestureHandlerRootView"] B --> C["Now Gestures Work!"] B --> D["Detects Taps"] B --> E["Detects Swipes"] B --> F["Detects Pinches"]

✋ 2. Gesture Types

What Are They?

Just like there are different ways to knock on a door (tap, bang, scratch), there are different types of gestures your fingers can make!

The Main Gesture Types

Gesture What It Does Real-Life Example
Tap Quick touch Pressing a doorbell 🔔
Pan Drag around Moving a chess piece ♟️
Pinch Two fingers squeeze Zooming a photo 📷
Rotation Two fingers twist Turning a dial 🎛️
LongPress Hold down Opening a secret menu 📜
Fling Quick swipe Flicking away a card 🃏

Code Example: Tap Gesture

import { Gesture, GestureDetector }
  from 'react-native-gesture-handler';

function MyButton() {
  const tap = Gesture.Tap()
    .onStart(() => {
      console.log('You tapped me!');
    });

  return (
    <GestureDetector gesture={tap}>
      <View style={styles.button}>
        <Text>Tap Me!</Text>
      </View>
    </GestureDetector>
  );
}

Code Example: Pan Gesture (Dragging)

const pan = Gesture.Pan()
  .onUpdate((event) => {
    // event.translationX = how far
    // you moved horizontally
    // event.translationY = how far
    // you moved vertically
    console.log(
      `Moved: ${event.translationX},
       ${event.translationY}`
    );
  });

🎯 Key Insight

Each gesture gives you different information:

  • Tap tells you where you tapped
  • Pan tells you how far you dragged
  • Pinch tells you how much you squeezed
  • Rotation tells you how much you rotated

🤝 3. Gesture Composition

What Is It?

Sometimes you want multiple gestures to work together! Like rubbing your tummy AND patting your head at the same time.

The Three Ways to Combine Gestures

graph TD A["Gesture Composition"] --> B["Simultaneous"] A --> C["Exclusive"] A --> D["Sequential"] B --> E["Both work at same time"] C --> F["Only one can win"] D --> G["One after another"]

1. Simultaneous (Both at Once)

Like walking and talking—you can do both!

const pinch = Gesture.Pinch();
const rotation = Gesture.Rotation();

// Both gestures work together
const combined = Gesture.Simultaneous(
  pinch,
  rotation
);

2. Exclusive (Only One Winner)

Like a race—only one person wins!

const tap = Gesture.Tap();
const longPress = Gesture.LongPress();

// If you hold long enough = longPress
// If you release quickly = tap
const combined = Gesture.Exclusive(
  longPress,
  tap
);

3. Sequential (One Then Another)

Like a recipe—step 1, then step 2!

const firstTap = Gesture.Tap();
const secondTap = Gesture.Tap();

// Must tap twice in a row
const doubleTap = Gesture.Sequence(
  firstTap,
  secondTap
);

💡 Real-World Example

Instagram photo viewer:

  • Simultaneous: Pinch to zoom + Rotate together
  • Exclusive: Single tap (show controls) vs Double tap (like photo)

💎 4. Shared Values

What Are They?

Here’s where the magic begins! Shared Values are special numbers that live on the “UI thread”—the super-fast highway where animations happen.

Simple Analogy

Imagine you have a magical notepad. When you write a number on it, your animation instantly sees the new number and updates—no waiting, no delay!

Regular variables are like sending a letter by mail ✉️—slow! Shared values are like telepathy 🧠—instant!

How to Create One

import { useSharedValue }
  from 'react-native-reanimated';

function MyComponent() {
  // Start at position 0
  const translateX = useSharedValue(0);

  // Change it anytime!
  translateX.value = 100;

  return <View />;
}

Shared Values in Gestures

const translateX = useSharedValue(0);
const translateY = useSharedValue(0);

const pan = Gesture.Pan()
  .onUpdate((event) => {
    // Update shared values as you drag
    translateX.value = event.translationX;
    translateY.value = event.translationY;
  });

🚀 Why So Fast?

graph TD A["Your Finger Moves"] --> B["Gesture Detects"] B --> C["Shared Value Updates"] C --> D["Animation Shows Instantly"] D --> E["60 FPS Smooth!"]

Regular React state causes re-renders (slow). Shared values skip all that and go straight to the animation!


🎨 5. useAnimatedStyle

What Is It?

This is how you connect your shared values to actual styles! It’s like connecting a puppet’s strings to your fingers.

Simple Analogy

  • Shared Value = Your hand position
  • useAnimatedStyle = The string
  • Animated.View = The puppet

When you move your hand, the puppet moves!

Basic Example

import Animated, {
  useSharedValue,
  useAnimatedStyle
} from 'react-native-reanimated';

function DraggableBox() {
  const translateX = useSharedValue(0);

  // This style AUTOMATICALLY updates
  // when translateX.value changes!
  const animatedStyle = useAnimatedStyle(
    () => ({
      transform: [
        { translateX: translateX.value }
      ],
    })
  );

  return (
    <Animated.View
      style={[styles.box, animatedStyle]}
    />
  );
}

🎯 Key Rules

  1. Always use Animated.View, not regular View
  2. Put your shared values inside useAnimatedStyle
  3. Return a style object from the function
  4. It updates automatically—no need to tell it!

Full Draggable Example

function DraggableBox() {
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);

  const pan = Gesture.Pan()
    .onUpdate((e) => {
      translateX.value = e.translationX;
      translateY.value = e.translationY;
    });

  const animatedStyle = useAnimatedStyle(
    () => ({
      transform: [
        { translateX: translateX.value },
        { translateY: translateY.value },
      ],
    })
  );

  return (
    <GestureDetector gesture={pan}>
      <Animated.View
        style={[styles.box, animatedStyle]}
      />
    </GestureDetector>
  );
}

✨ 6. Reanimated Animations

What Are They?

So far, things move exactly where your finger goes. But what if you want things to spring, bounce, or glide smoothly? That’s where animation functions come in!

The Three Animation Types

Type How It Feels Use Case
withTiming Smooth and predictable Fading, sliding
withSpring Bouncy and natural Buttons, cards
withDecay Keeps going, then stops Scrolling, flicking

withTiming (Smooth Transition)

import { withTiming }
  from 'react-native-reanimated';

// Move to position 200 over 500ms
translateX.value = withTiming(200, {
  duration: 500,
});

withSpring (Bouncy Fun!)

import { withSpring }
  from 'react-native-reanimated';

// Bounce to position 200
translateX.value = withSpring(200, {
  damping: 10,      // Less = more bouncy
  stiffness: 100,   // More = faster
});

withDecay (Momentum)

import { withDecay }
  from 'react-native-reanimated';

// Continue moving based on velocity
pan.onEnd((e) => {
  translateX.value = withDecay({
    velocity: e.velocityX,  // How fast
    deceleration: 0.998,    // Friction
  });
});

Complete Example: Swipe Card

function SwipeCard() {
  const translateX = useSharedValue(0);

  const pan = Gesture.Pan()
    .onUpdate((e) => {
      // Follow finger exactly
      translateX.value = e.translationX;
    })
    .onEnd(() => {
      // Spring back to center!
      translateX.value = withSpring(0);
    });

  const style = useAnimatedStyle(() => ({
    transform: [
      { translateX: translateX.value }
    ],
  }));

  return (
    <GestureDetector gesture={pan}>
      <Animated.View style={[
        styles.card,
        style
      ]} />
    </GestureDetector>
  );
}
graph TD A["Finger Drags"] --> B["onUpdate"] B --> C["translateX = finger position"] A --> D["Finger Releases"] D --> E["onEnd"] E --> F["withSpring back to 0"] F --> G["Card bounces back!"]

🎓 Putting It All Together

Here’s everything working together:

import {
  Gesture,
  GestureDetector,
  GestureHandlerRootView
} from 'react-native-gesture-handler';

import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
} from 'react-native-reanimated';

function App() {
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);
  const scale = useSharedValue(1);

  const pan = Gesture.Pan()
    .onUpdate((e) => {
      translateX.value = e.translationX;
      translateY.value = e.translationY;
    })
    .onEnd(() => {
      translateX.value = withSpring(0);
      translateY.value = withSpring(0);
    });

  const pinch = Gesture.Pinch()
    .onUpdate((e) => {
      scale.value = e.scale;
    })
    .onEnd(() => {
      scale.value = withSpring(1);
    });

  const combined = Gesture.Simultaneous(
    pan,
    pinch
  );

  const style = useAnimatedStyle(() => ({
    transform: [
      { translateX: translateX.value },
      { translateY: translateY.value },
      { scale: scale.value },
    ],
  }));

  return (
    <GestureHandlerRootView
      style={{ flex: 1 }}>
      <GestureDetector gesture={combined}>
        <Animated.View
          style={[styles.box, style]}
        />
      </GestureDetector>
    </GestureHandlerRootView>
  );
}

🌟 Summary

Concept What It Does Remember It As
Gesture Handler Setup Enables gesture detection Install the detective
Gesture Types Different finger actions Tap, Pan, Pinch, etc.
Gesture Composition Combine multiple gestures Teamwork makes dream work
Shared Values Super-fast animation data Telepathic numbers
useAnimatedStyle Connect values to styles Puppet strings
Reanimated Animations Add physics and timing withSpring, withTiming

🚀 You Did It!

You now understand how to make your React Native app respond to touch like a professional app!

Remember:

  1. Set up Gesture Handler first
  2. Choose the right gesture type
  3. Combine them if needed
  4. Store values in shared values
  5. Connect with useAnimatedStyle
  6. Animate with withSpring/withTiming

Go make something amazing! 🎉

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.