Окружающая среда
- React Native: 0.79.5
- React Native Reanimated: 3.17.4
- Платформа: Android (не встречается в iOS)
- Навигация: пользовательская навигация по вкладкам с анимацией затухания/масштабирования
При переключении между вкладками у меня есть пользовательская анимация затухания и масштабирования (затухание 200 мс, появление 300 мс). Непрозрачность экрана анимируется корректно, но тени Android при возвышении не исчезают вместе с экраном — они остаются полностью непрозрачными, пока экран тускнеет, создавая визуальный сбой.
Визуальное описание:
- Экран плавно исчезает от непрозрачности 1 → 0
- Тени остаются полностью непрозрачными на протяжении всего затухания.
- Результат: тени видны «плавающими» на полупрозрачном экране.
Я использую настраиваемый навигатор вкладок с анимированным API для переходов:
Код: Выделить всё
// MainTab.tsx - handleTabChange
const handleTabChange = useCallback((newTab: number) => {
if (newTab === currentTab) return;
// Immediately remove shadows BEFORE animation starts
if (currentTab === 0) {
removeHomeShadows();
} else if (currentTab === 1) {
removeScheduleShadows();
} else if (currentTab === 4) {
removeSettingsShadows();
}
// Screen fade animation
Animated.parallel([
Animated.timing(currentScreenAnim.opacity, {
toValue: 0,
duration: 200,
useNativeDriver: true,
easing: Easing.out(Easing.quad),
}),
Animated.timing(currentScreenAnim.scale, {
toValue: 0.8,
duration: 200,
useNativeDriver: true,
}),
]).start();
}, [currentTab]);
Код: Выделить всё
// SummaryHeader.tsx (Home screen buttons)
let removeHomeShadowsCallback: (() => void) | null = null;
export const removeHomeShadows = () => {
removeHomeShadowsCallback?.();
};
const SummaryHeader = memo(() => {
const [shadowsRemoved, setShadowsRemoved] = useState(false);
useEffect(() => {
removeHomeShadowsCallback = () => {
setShadowsRemoved(true);
};
return () => {
removeHomeShadowsCallback = null;
};
}, []);
return (
);
});
- Немедленное удаление теней с помощью обратных вызовов: удаление теней синхронно перед началом анимации (текущий подход)
- Работает большую часть времени, но периодически дает сбои
- Проблема: обновления состояния React являются асинхронными, поэтому некоторые компоненты могут не работать обновить вовремя
- useIsFocused ловушка: удалить тени, когда экран теряет фокус
- Слишком медленно — тени все еще видны во время перехода
- Недостаточно синхронно
- Переполнение контейнера: скрыто: Клип тени на уровне контейнера
- Помогает, но не полностью решает периодически возникающую проблему
- Анимированная непрозрачность теней: Пробовал анимировать непрозрачность теней
- не поддерживает анимацию в React Native
Код: Выделить всё
elevation - Невозможно использовать useAnimatedStyle с возвышением (известное ограничение)
- Различные типы перехода: пробовал только затухание, только скольжение
- Проблема сохраняется — это конкретно возвышение свойство, которое не анимируется
- — это собственное свойство Android, которое не поддерживает анимацию с помощью Animated API React Native
Код: Выделить всё
elevation - требуется для производительности, но тени не могут использовать собственный драйвер.
Код: Выделить всё
useNativeDriver: true - Требуется синхронное удаление теней (обновления состояния React являются асинхронными).
- Несколько компонентов с тенями (кнопки, элементы списка, раскрывающиеся списки) на разных экранах.
Я нашел эту проблему на GitHub Поддержка анимации boxShadow в Reanimated, но речь идет конкретно о boxShadow (веб/CSS), а не о повышении Android.
Вопрос
Как обеспечить синхронное удаление теней Android до начала переходов экрана или, альтернативно, как заставить тени исчезать вместе с непрозрачностью экрана?
прерывистый характер предполагает состояние гонки между:
- обновлением состояния React (асинхронно)
- запуском анимации (синхронно)
- повторным рендерингом компонента (асинхронно)
- принудительно выполнить синхронное удаление теней, не зависящее от React состояние?
- Использовать другой подход к теням, которые можно анимировать?
- Убедиться, что все затененные компоненты обновляются до начала анимации?
Код: Выделить всё
// Tab navigation with fade transition
const handleTabChange = (newTab: number) => {
// Remove shadows (async state update)
setShadowsRemoved(true);
// Start animation immediately (synchronous)
Animated.timing(opacity, {
toValue: 0,
duration: 200,
useNativeDriver: true,
}).start();
// Problem: Animation starts before all components update shadows
};
// Component with elevation

Будем очень признательны за любые предложения или альтернативные подходы!>
Подробнее здесь: https://stackoverflow.com/questions/798 ... s-in-react
Полная версия