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

withRepeat is flickering on android

Open MingHieu opened this issue 1 year ago • 5 comments

Description

I'm having a great experience with the animation using withTiming, but when I wrap it with withRepeat, it causes flickering.

Code:

const useMicrophoneAnimation = (isRecording: boolean) => {
  const circleSize = useSharedValue(0);
  const circleOpacity = useSharedValue(0.8);

  const circle1AnimatedStyles = useAnimatedStyle(() => ({
    width: circleSize.value,
    height: circleSize.value,
    opacity: circleOpacity.value,
  }));

  const circle2AnimatedStyles = useAnimatedStyle(() => ({
    width: circleSize.value * 1.4,
    height: circleSize.value * 1.4,
    opacity: circleOpacity.value * 0.9,
  }));

  const circle3AnimatedStyles = useAnimatedStyle(() => ({
    width: circleSize.value * 1.8,
    height: circleSize.value * 1.8,
    opacity: circleOpacity.value * 0.8,
  }));

  useEffect(() => {
    cancelAnimation(circleSize);
    cancelAnimation(circleOpacity);
    circleSize.value = 0;
    circleOpacity.value = 0.8;
    if (isRecording) {
      circleSize.value = withRepeat(withTiming(110, {duration: 1000}), -1);
      circleOpacity.value = withRepeat(withTiming(0, {duration: 1000}), -1);
    }
  }, [isRecording, circleSize, circleOpacity]);

  return {circle1AnimatedStyles, circle2AnimatedStyles, circle3AnimatedStyles};
};
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);

<View style={styles.microphoneAnimationWrapper}>
  <AnimatedPressable
    onPress={toggleRecord}
    onPressIn={() => {
      microphoneSize.value = withSpring(0.9);
    }}
    onPressOut={() => {
      microphoneSize.value = withSpring(1);
    }}
    style={[
      styles.microphoneWrapper,
      {
        backgroundColor: color.primary,
        transform: [{scale: microphoneSize}],
      },
    ]}>
    <Image source={require('~assets/images/microphone.png')} />
  </AnimatedPressable>
  <Animated.View
    style={[
      circle1AnimatedStyles,
      styles.microphoneAnimationCircle,
      {backgroundColor: color.primary},
    ]}
  />
  <Animated.View
    style={[
      circle2AnimatedStyles,
      styles.microphoneAnimationCircle,
      {backgroundColor: color.primary},
    ]}
  />
  <Animated.View
    style={[
      circle3AnimatedStyles,
      styles.microphoneAnimationCircle,
      {backgroundColor: color.primary},
    ]}
  />
</View>;

https://github.com/software-mansion/react-native-reanimated/assets/77161145/02bd4094-d951-42f2-8710-f9b651d40390

Steps to reproduce

NA

Snack or a link to a repository

NA

Reanimated version

^3.11.0

React Native version

0.74.1

Platforms

Android

JavaScript runtime

None

Workflow

React Native

Architecture

Paper (Old Architecture)

Build type

None

Device

Android emulator

Device model

Pixel_4_API_34 ( android 14 )

Acknowledgements

Yes

MingHieu avatar Jun 10 '24 04:06 MingHieu

Hey! 👋

It looks like you've omitted a few important sections from the issue template.

Please complete Steps to reproduce and Snack or a link to a repository sections.

github-actions[bot] avatar Jun 10 '24 04:06 github-actions[bot]

Are you creating the AnimatedPressable out of component ?

paragbarsar99 avatar Jun 13 '24 17:06 paragbarsar99

Are you creating the AnimatedPressable out of component ?

Yes, is anything wrong?

MingHieu avatar Jun 13 '24 17:06 MingHieu

Hey! If you encounter this issue, can you try using the following code and let me know if it works?

circleSize.value = withRepeat(
    withSequence(
      withTiming(110, { duration: 1000 }),
      withTiming(0, { duration: 0 })
    ),
    -1
  );
  circleOpacity.value = withRepeat(
    withSequence(
      withTiming(0, { duration: 1000 }),
      withTiming(0.8, { duration: 0 })
    ),
    -1
  );
}

Basically, I add withSequence to the withRepeat, which resets the value to the desired initial value. Duration is set to 0, so the value should retain its initial state immediately.

I was trying to reproduce the issue using the latest reanimated version but I cannot see the problem, even if I was using the same code as provided in this issue repro. Maybe upgrading reanimated to the latest version will help you as well with no need to update the implementation.

MatiPl01 avatar Jul 02 '24 13:07 MatiPl01

Hi! It makes sense. I've faced the same problem.

exzos28 avatar Jul 15 '24 18:07 exzos28

@MatiPl01 it doesn't help

exzos28 avatar Jul 15 '24 18:07 exzos28

@MatiPl01 it doesn't help

Can you provide a repro? I will take a look and check what is wrong.

MatiPl01 avatar Jul 15 '24 18:07 MatiPl01

@MatiPl01 https://snack.expo.dev/-dhxdfPtAoOXMlvtSavoY

exzos28 avatar Jul 15 '24 18:07 exzos28

Locally, it looks like this

https://github.com/user-attachments/assets/3c6e30ac-d189-42f4-b5ed-1e426a09dbe4

There is a weird frame image

exzos28 avatar Jul 15 '24 18:07 exzos28

it looks like the error is present when position: absolute and opacity are used. If opacity is 1 or absolute is not used, everything is ok.

exzos28 avatar Jul 15 '24 19:07 exzos28

it looks like the error is present when position: absolute and opacity are used. If opacity is 1 or absolute is not used, everything is ok.

Thank you for explanation. I can reproduce the issue but only on Android. Have you tested on iOS as well (and if you tested, have you seen the same issue on iOS)?

MatiPl01 avatar Jul 16 '24 10:07 MatiPl01

@MatiPl01 ios and web are okay

exzos28 avatar Jul 16 '24 10:07 exzos28

@MatiPl01 ios and web are okay

Thanks, I will look into that. Thank you for details.

MatiPl01 avatar Jul 16 '24 10:07 MatiPl01