DEV Community

Cover image for How to add animations to your NativeBase App
NativeBase
NativeBase

Posted on • Updated on • Originally published at nativebase.io

How to add animations to your NativeBase App

Introduction

What is the difference between a “Good” app and a “Great” app?

When I think about this question, a few things come to mind. But the one thing that most users will notice and remember is Interaction Animations.

So, in this tutorial, we will share with you, how to add animations to your NativeBase app, using Reanimated.

What are We Creating

We will create a Todo app and add interaction animations to it, to enhance the user experience.

To make our Todo app lively and enjoyable, we will use the three animations highlighted below.

  1. Add a small rotate the button on click.
  2. Change the background color of the completed item when clicked.
  3. Animating removing items from the list by swiping the item left.

Image description

Implementing Individual Animations

  • Rotation 🔁
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withTiming,
  useDerivedValue,
  interpolate,
  withRepeat,
} from "react-native-reanimated";
const animation = useSharedValue(0);
const rotation = useDerivedValue(() => {
  return interpolate(animation.value, [0, 360], [0, 360]);
});
const buttonRotation = useAnimatedStyle(() => {
  return {
    transform: [
      {
        rotate: rotation.value + "deg",
      },
    ],
  };
});
const startAnimation = () => {
  animation.value = withRepeat(
    withTiming(30, {
      duration: 400,
    }),
    2,
    true
  );
};
const buttonRotation = useAnimatedStyle(() => {
  return {
    transform: [
      {
        rotate: rotation.value + "deg",
      },
    ],
  };
});

// JSX for button
<TouchableWithoutFeedback
  onPress={() => {
    if (inputValue) addItem(inputValue);
    setInputValue("");
  }}
  onPressIn={startAnimation}
>
  <Animated.View
    style={[
      {
        height: 50,
        width: 100,
        backgroundColor: colors["primary"][700],
        borderRadius: 3,
        alignItems: "center",
        justifyContent: "center",
        paddingHorizontal: 12,
      },
      buttonRotation,
    ]}
  >
    <Text
      color="white"
      textAlign="center"
      fontSize="md"
      justifyContent="center"
    >
      Add Task
    </Text>
  </Animated.View>
</TouchableWithoutFeedback>
Enter fullscreen mode Exit fullscreen mode

Rotation can act as the base for tons of cool interactions. We used useSharedValue hook from the reanimated library to share the value between the react-native UI thread and animation thread.

To get the transformed shared value if one of the underlying shared value change, we have used the useDerivedValue hook. We then used the useAniamtedStyle hook to make the association between the shared values and the view properties of add button.

By clicking on the button, the start animation function is called. This changes the shared value and all the subsequent changes occur based on the shared value used in animations. The video below demonstrates, what it looks like 🙂.

Image description

  • Changing of background color on click 🎨

We inserted this animation to show that a certain task is pending. We are changing the background color as shown below to denote the completion of the task. Here we are changing the backgroundColor property of the view with some delay animation.

const { colors } = useTheme();
const progress = useDerivedValue(() => {
  return props.item.isCompleted
    ? withTiming(1, { duration: 2000 })
    : withTiming(0, { duration: 2000 });
});
const rContainreStyle = useAnimatedStyle(() => {
  const backgroundColor = interpolateColor(
    progress.value,
    [0, 1],
    ["white", colors["muted"][100]]
  );
  return {
   ..
   backgroundColor,
   ..
  };
});


//JSX
<Pressable
  onPress={() => {
    props.handleStatusChange(props.itemI);
  }}
>
  <PanGestureHandler onGestureEvent={gestureMethod}>
    <Animated.View style={[styles.containreStyle, rContainreStyle]}>
      <Text fontSize="lg" px={6} color="coolGray.800">
        {props.item.title}
      </Text>
    </Animated.View>
  </PanGestureHandler>
</Pressable>
Enter fullscreen mode Exit fullscreen mode

useTheme hook offered by NativeBase and allows you to tap into the theming system provided by NativeBase. The video below demonstrates this animation.

Image description

  • Removing the card 🗑️

We used this animation to show that once we complete a task we just simply slide the card left 👈. With one swipe the card is removed.

Using PanGestureHandler from react-native-gesture-handler to capture touch event and based on the swipe value assigned we animated the translateX, marginVertical, opacity, and height properties of view.

import { PanGestureHandler } from "react-native-gesture-handler";
const SCREENWIDTH = Dimensions.get("window").width;
const TRANSLATEXTHRESHOLD = -SCREENWIDTH * 0.34;
const translateX = useSharedValue(0);
const MARGIN = useSharedValue(10);
const CONTAINERHEIGHT = useSharedValue(70);
const OPACITY = useSharedValue(1);
const gestureMethod = useAnimatedGestureHandler({
  onStart: (event, ctx) => {},
  onActive: (event, ctx) => {
    translateX.value = event.translationX;
  },
  onEnd: (event, ctx) => {
    const isDismissed = translateX.value < TRANSLATEXTHRESHOLD;
    if (isDismissed) {
      translateX.value = withTiming(-SCREENWIDTH);
      CONTAINERHEIGHT.value = withTiming(0);
      MARGIN.value = withTiming(0);
      OPACITY.value = withTiming(0);
    } else {
      translateX.value = withTiming(0);
    }
  },
});
const rContainreStyle = useAnimatedStyle(() => {
  const backgroundColor = interpolateColor(
    progress.value,
    [0, 1],
    ["white", colors["muted"][100]]
  );
  return {
    transform: [{ translateX: translateX.value }],
    height: CONTAINERHEIGHT.value,
    opacity: OPACITY.value,
    marginVertical: MARGIN.value,
    backgroundColor,
  };
});

//JSX
<Pressable
  onPress={() => {
    props.handleStatusChange(props.itemI);
  }}
>
  <PanGestureHandler onGestureEvent={gestureMethod}>
    <Animated.View style={[styles.containreStyle, rContainreStyle]}>
      <Text fontSize="lg" px={6} color="coolGray.800">
        {props.item.title}
      </Text>
    </Animated.View>
  </PanGestureHandler>
</Pressable>
Enter fullscreen mode Exit fullscreen mode

The video below demonstrates the animation:

Image description

Conclusion

Animation plays a very pivotal role in enhancing the overall user experience of any application. The experience of a simple application can be improved ten folds by the use of simple animations.

For achieving that outcome React animated plays an important role. NativeBase being an awesome Library offered such a variety to use components and Pseudo props that helped in reducing the code complexity and improving the code quality.

With the use of NativeBase what we can achieve is something great. The experience of using apps essentials in everyday life, like the ToDo application, can be enhanced incredibly using animations from NativeBase.

Top comments (0)