react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

Animated View Cause Screen Freeze on Android and Won't allow any Interaction

Open vatsal-bk opened this issue 6 months ago • 11 comments

Description

I am using Animated View for the StyleSheet in React native. It causes Screen Freeze on Android Device only

import React from "react";
import styled, { useTheme } from "styled-components/native";
import { Dimensions, Modal, Platform, TouchableOpacity } from "react-native";
import { ModalProps } from "@components/atoms/SlideSheet/types";
import VDBIcon, { IconsVariant } from "@components/icons/VDBIcon";
import { VDBText } from "..";
import { useTypographyStore } from "@redux/slices/typographySlice";
import { SpaceType } from "../Spacer/types";
import { VDBIcons } from "@utils/VDBIcons";
import { KeyboardAwareScrollView } from "react-native-keyboard-controller";
import Animated, { FadeIn, SlideInDown } from "react-native-reanimated";

const SlideSheet = ({
  headerTitle,
  children,
  onClose,
  isOpen,
  paddingLeft,
  paddingRight,
  paddingTop,
  paddingBottom,
  backgroundColor,
  skipKeyboardAware,
  allowFullScreen,
}: ModalProps) => {
  const typography = useTypographyStore();
  const handleCloseModal = () => {
    onClose?.();
  };
  const theme = useTheme();
  const windowHeight = Dimensions.get(
    allowFullScreen ? "screen" : "window"
  ).height;

  return (
    <Modal animationType="none" transparent={true} visible={isOpen}>
      <Background entering={FadeIn} />
      <Overlay entering={SlideInDown}>
        <ModalBox backgroundColor={backgroundColor} windowHeight={windowHeight}>
          <OverlapContainer>
            <Header>
              <VDBText
                textAlign="center"
                type={typography["H2-M"]}
                color={theme["core-05"]}
              >
                {headerTitle}
              </VDBText>
            </Header>
            <ButtonContainer>
              <TouchableOpacity onPress={handleCloseModal}>
                <VDBIcon
                  name={VDBIcons.CLOSE_CIRCLE}
                  variant={IconsVariant.VDBCustom}
                  size={24}
                  color={theme["core-06"]}
                />
              </TouchableOpacity>
            </ButtonContainer>
          </OverlapContainer>

          <LineView />
          <ScrollViewContainer
            paddingLeft={paddingLeft}
            paddingRight={paddingRight}
            paddingBottom={paddingBottom}
            paddingTop={paddingTop}
          >
            {!skipKeyboardAware ? (
              <KeyboardAwareScrollView
                bottomOffset={20}
                keyboardShouldPersistTaps="always"
              >
                {children}
              </KeyboardAwareScrollView>
            ) : (
              <FullModal>{children}</FullModal>
            )}
          </ScrollViewContainer>
        </ModalBox>
      </Overlay>
    </Modal>
  );
};

const FullModal = styled.View`
  height: 100%;
`;

const Overlay = styled(Animated.View)`
  flex: 1;
  flex-direction: column;
  justify-content: flex-end;
`;

const Background = styled(Animated.View)`
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
`;

const ModalBox = styled.View<{
  backgroundColor?: string;
  windowHeight?: any;
}>`
  background-color: ${({ theme, backgroundColor }) =>
    backgroundColor ? backgroundColor : theme["core-01"]};
  border-top-left-radius: 16px;
  border-top-right-radius: 16px;
  max-height: ${({ windowHeight }) => `${windowHeight * 0.9}px`};
`;

const OverlapContainer = styled.View`
  position: relative;
  flex-direction: row;
  background-color: ${({ theme }) => theme["core-02"]};
  border-top-left-radius: 16px;
  border-top-right-radius: 16px;
`;

const Header = styled.View<any>`
  flex: 1;
  padding-left: ${SpaceType.Double}px;
  padding-right: ${SpaceType.Double}px;
  padding-top: ${({ theme }) =>
    SpaceType.Double +
    (Platform.OS === "ios" && (theme.isDesktop || theme.isTablet) ? 2 : 0)}px;
  padding-bottom: ${({ theme }) =>
    SpaceType.Double +
    (Platform.OS === "ios" && (theme.isDesktop || theme.isTablet) ? 2 : 0)}px;
`;

const ButtonContainer = styled.View`
  position: absolute;
  top: 1px;
  right: 2px;
  margin: ${SpaceType.Extra}px;
`;

const LineView = styled.View`
  height: 1px;
  background-color: ${({ theme }) => theme["core-03"]};
`;

const ScrollViewContainer = styled.View<any>`
  flex: 1;
  flex-basis: auto;
  ${({ paddingLeft }) => (paddingLeft ? `padding-left: ${paddingLeft}px;` : 0)}
  ${({ paddingRight }) =>
    paddingRight ? `padding-right: ${paddingRight}px;` : 0}
  ${({ paddingTop }) => (paddingTop ? `padding-top: ${paddingTop}px;` : 0)}
  ${({ paddingBottom }) =>
    paddingBottom ? `padding-bottom: ${paddingBottom}px;` : 0}
`;

export default SlideSheet;

Steps to reproduce

  1. Open this Component and App got freeze
  2. If I Remove Animated then it work as expected and allow Interaction

Snack or a link to a repository

https://github.com/software-mansion/react-native-reanimated

Reanimated version

3.17.4

React Native version

0.79.2

Platforms

Android

JavaScript runtime

None

Workflow

Expo Go

Architecture

None

Build type

Release app & production bundle

Device

Real device

Host machine

None

Device model

No response

Acknowledgements

Yes

vatsal-bk avatar Jun 19 '25 05:06 vatsal-bk

I provided the Exact Code and Here is the minimal implementation - https://snack.expo.dev/@vatsalvdb/modal-with-animated-view

vatsal-bk avatar Jun 19 '25 05:06 vatsal-bk

@Vatsal4GVM Did you find any solution? My android app also freezes while using Animated View on Android. react-native: 0.79.4 react-native-reanimated: 3.18.0 expo: 53.0.0 react-native-unistyles: 2.20.0 I am using the old arch

Brma1048 avatar Jun 26 '25 08:06 Brma1048

UPDATE 04/07/2025: it's not working. Leaving the old content here:

What I did, but it's not working I faced this problem also in [3.17.5](https://github.com/software-mansion/react-native-reanimated/releases/tag/3.17.5) that says it is fixed: > fix: Animations on android not working if multiple styles objects are present in the props vector by @MatiPl01 in https://github.com/software-mansion/react-native-reanimated/pull/7422

In my case I have a simple Animated.View overlay.

  • with just the style prop will work perfectly.
  • Introducing an exiting prop, it will break

The consequence is that the app freezes and becomes unresponsive. It's like it is not disappearing properly from the Render Tree and it stays there, not letting anything below to be touched.

    <Animated.View
      // exiting={FadeOut} <= app unresponsive if added
      style={{
        flex: 1,
        position: 'absolute',
        top: 0,
        left: 0,
        right: 0,
        bottom: 0,
      }}
    >

With 3.18.0 the problem seems to be gone for me. Before testing, I updated to the last Expo 53 available (right now "expo": "53.0.16") deleted the node_modules, android and iOS folders and regenerate them. If it's not working for you, check npx expo install --check (with an error on reanimated that we expect) or expo doctor.

So yeah, I can still reproduce the problem, even with the latest Expo and Reanimated, updated today. I tried to reproduce the problem with a minimal repo, but it seems to work perfectly, so I'm trying to isolate the problem in the "real" project.

Martinocom-Switcho avatar Jul 03 '25 14:07 Martinocom-Switcho

@Martinocom-Switcho One little clarification here. The fix shipped in 3.17.5 that you mentioned was not related to layout animation freezes/crashes. It just fixed style inconsistence for worklet-based animations (these created with useAnimatedStyle and Shared Values) on Android.

The issue reported here seems to be related to layout animations instead of worklet-based animations.

MatiPl01 avatar Jul 03 '25 14:07 MatiPl01

  • https://github.com/software-mansion/react-native-reanimated/issues/7723

@Vatsal4GVM Related with repo provided? Rolling back to 3.16.1 as suggested here seems to work.

Martinocom-Switcho avatar Jul 04 '25 10:07 Martinocom-Switcho

@Martinocom-Switcho Sure but is that version is compatible with Expo SDK 53?

vatsal-bk avatar Jul 04 '25 11:07 vatsal-bk

Not declared as compatible, but if it works, it works 🤷 . But as you can see, even if declared as "compatible", it still has problems. So for me "compatibility" is a loose concept as usual: if it's a minor upgrade/downgrade, it shouldn't be problematic.

Spoiler: it still does not work perfectly in some cases (but probably unrelated?). Sometimes positioning of absolute elements is flickering. With previous Expo^52.0.25 and reanimated ^3.16.1 and we have no such problems. This is what happens with entering animation enabled:

https://github.com/user-attachments/assets/fb64f816-84ea-470d-929f-d5b8acc2c1e7

PS: yes we're migrating to 53 and we're holding back for various reasons.

Martinocom-Switcho avatar Jul 04 '25 12:07 Martinocom-Switcho

I have same issue with "react-native": "0.76.9" and "react-native-reanimated": "3.18.0" on Android iOS works fine. Simple reproducible with next component export function LoadingContainer({loading}:{ loading: boolean }) { return ( loading ? ( <Animated.View entering={FadeIn} exiting={FadeOut} style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', backgroundColor: colorOpacity(Colors.black, 0.66), zIndex: 300 }} > <ActivityIndicator size='large' color='white' /> </Animated.View> ):null ) }

After loading is set from true to false Animated.View not removed from stack. Comenting out exiting={FadeOut} fixes issue.

igorkos avatar Aug 05 '25 19:08 igorkos

@igorkos 3.18.0 had a regression that introduced this exiting animations issue on the Old Architecture. You'd have to bump reanimated to 3.19.0 for the issue to be fixed (and also probably bump RN version to 0.78).

Downgrading to reanimated 3.16.7 or other version before 3.18.0 (not sure when exactly the issue was introduced) should also fix the issue.

MatiPl01 avatar Aug 05 '25 21:08 MatiPl01

As mentioned here (https://github.com/software-mansion/react-native-reanimated/issues/7842#issuecomment-3117517108) I was able to fix my flickering putting collapsable=false to that particular animated view and updating to 3.19.

I discovered that because putting background to that view solved the problem (thx MatiPl01 for pointing that out)

As for the "freeze", the 3.19 solved it for me.

Martinocom-Switcho avatar Aug 06 '25 08:08 Martinocom-Switcho

@MatiPl01 3.19 is causing crash on android and ios for some users #8453 I am using react native 0.79.6. Is it fine to downgrade to 3.16.7, as it's not compatible?

valesh-gosats avatar Oct 29 '25 04:10 valesh-gosats