Тени возвышений Android остаются видимыми во время переходов затухания экрана в React NativeAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Тени возвышений Android остаются видимыми во время переходов затухания экрана в React Native

Сообщение Anonymous »

Я столкнулся с визуальным сбоем на Android: тени высоты остаются видимыми во время перехода между экранами, хотя сам экран затемняется. Это создает резкий эффект, когда тени кажутся «плавающими» по тускнеющему экрану.
Окружающая среда
  • 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 ловушка: удалить тени, когда экран теряет фокус
    • Слишком медленно — тени все еще видны во время перехода
    • Недостаточно синхронно
  • Переполнение контейнера: скрыто: Клип тени на уровне контейнера
    • Помогает, но не полностью решает периодически возникающую проблему
  • Анимированная непрозрачность теней: Пробовал анимировать непрозрачность теней
    • Код: Выделить всё

      elevation
      не поддерживает анимацию в React Native
    • Невозможно использовать useAnimatedStyle с возвышением (известное ограничение)
  • Различные типы перехода: пробовал только затухание, только скольжение
    • Проблема сохраняется — это конкретно возвышение свойство, которое не анимируется
Ключевые ограничения
  • Код: Выделить всё

    elevation
     — это собственное свойство Android, которое не поддерживает анимацию с помощью Animated API React Native
  • Код: Выделить всё

    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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»