Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Основы анимации

Анимация — плавное изменение стиля во времени: прозрачности, положения, размера. На телефоне она подсказывает, что произошло: новая задача плавно появилась, удалённая — исчезла. В React Native есть встроенный модуль Animated, а для сложных случаев — библиотека Reanimated.

Animated: плавное появление

Сделаем обёртку, которая проявляет содержимое за 400 миллисекунд:

// components/FadeIn.tsx
import { type ReactNode, useEffect, useRef } from 'react';
import { Animated } from 'react-native';
 
export default function FadeIn({ children }: { children: ReactNode }) {
  const opacity = useRef(new Animated.Value(0)).current;
 
  useEffect(() => {
    Animated.timing(opacity, {
      toValue: 1,
      duration: 400,
      useNativeDriver: true,
    }).start();
  }, [opacity]);
 
  return <Animated.View style={{ opacity }}>{children}</Animated.View>;
}

Как это работает:

  1. Animated.Value(0) — анимируемое число, начальная прозрачность 0. useRef сохраняет его между рендерами.
  2. Animated.View — View, который понимает такие значения в style.
  3. Animated.timing меняет значение до toValue за duration миллисекунд, start() запускает анимацию.
  4. useNativeDriver: true отдаёт анимацию родному коду, и она остаётся плавной, даже если JavaScript занят.

Использование

Оберните строку задачи в renderItem списка:

// app/index.tsx
import FadeIn from '@/components/FadeIn';
 
renderItem={({ item }) => (
  <FadeIn>
    <TaskItem task={item} onToggle={toggleTask} />
  </FadeIn>
)}

Добавьте задачу — она не появится резко, а плавно проявится. Задачи, которые уже были на экране, не мигают: анимация срабатывает только при первом показе компонента.

Что можно анимировать с useNativeDriver

МожноНельзя
opacitywidth, height
transform: сдвиг, масштаб, поворотbackgroundColor
margin, padding

Для свойств раскладки useNativeDriver ставят false, но такая анимация менее плавная.

Reanimated

Библиотека react-native-reanimated уже установлена в шаблоне Expo. Она выполняет анимацию целиком в родном потоке и даёт готовые анимации появления и исчезновения:

// components/TaskItem.tsx
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
 
<Animated.View entering={FadeIn} exiting={FadeOut}>
  <Text>{task.title}</Text>
</Animated.View>

С entering и exiting задача плавно появляется при добавлении и плавно исчезает при удалении — без ручных значений и эффектов. Для анимаций, управляемых вручную, у Reanimated есть хуки useSharedValue и useAnimatedStyle и функция withTiming.

Частая ошибка

Создавать Animated.Value прямо в теле компонента: const opacity = new Animated.Value(0);. При каждом рендере появляется новое значение, равное нулю, и анимация сбрасывается или не идёт вовсе. Храните его в useRef, как в примере.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.