Skip to content

Android - Animated.event useNativeDriver:true sets incorrect translate position when scrolling interrupted by user #50496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
kocburak opened this issue Apr 4, 2025 · 23 comments
Labels
Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules)

Comments

@kocburak
Copy link
Contributor

kocburak commented Apr 4, 2025

Description

I have 2 transform translateY animation. When the useNativeDriver:false, there is no issue except performance. I can see the animation moves couple frames behind from native animation. When the useNativeDriver:true, while moving fast the component jumps around (usually to final position if there were no distruption to moementum scroll)

Steps to reproduce

  1. Install the application to you andorid using npx expo run:android --device while useNativeDriver: true
  2. Make a slide with momentum and while momentum exists stop and make small movement and remove you finger from screen. (see the video)

React Native Version

0.77.2

Affected Platforms

Runtime - Android

Output of npx @react-native-community/cli info

info Fetching system and libraries information...
System:
  OS: Windows 10 10.0.19045
  CPU: (16) x64 Intel(R) Core(TM) i7-10870H CPU @ 2.20GHz
  Memory: 17.67 GB / 31.84 GB
Binaries:
  Node:
    version: 22.14.0
    path: C:\Program Files\nodejs\node.EXE
  Yarn:
    version: 1.22.22
    path: ~\AppData\Roaming\npm\yarn.CMD
  npm:
    version: 11.2.0
    path: C:\Program Files\nodejs\npm.CMD
  Watchman: Not Found
SDKs:
  Android SDK:
    API Levels:
      - "22"
      - "33"
      - "33"
      - "33"
      - "34"
      - "35"
    Build Tools:
      - 30.0.2
      - 30.0.3
      - 33.0.1
      - 34.0.0
      - 35.0.0
      - 35.0.1
    System Images:
      - android-34 | Google APIs Intel x86_64 Atom
      - android-35 | AOSP ATD Intel x86_64 Atom
      - android-35 | Intel x86_64 Atom
      - android-35 | Google APIs Intel x86_64 Atom
    Android NDK: Not Found
  Windows SDK:
    AllowDevelopmentWithoutDevLicense: Enabled
    Versions:
      - 10.0.19041.0
      - 10.0.22621.0
IDEs:
  Android Studio: AI-242.23726.103.2422.13016713
  Visual Studio:
    - 17.13.35825.156 (Visual Studio Community 2022)
Languages:
  Java: 17.0.7
  Ruby: Not Found
npmPackages:
  "@react-native-community/cli":
    installed: 15.1.3
    wanted: ^15.1.0
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.77.2
    wanted: ^0.77.2
  react-native-windows: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found

info React Native v0.78.2 is now available (your project is running on v0.77.2).
info Changelog: https://github.com/facebook/react-native/releases/tag/v0.78.2
info Diff: https://react-native-community.github.io/upgrade-helper/?from=0.77.2&to=0.78.2
info For more info, check out "https://reactnative.dev/docs/upgrading?os=windows".

Stacktrace or Logs

N/A

Reproducer

https://snack.expo.dev/@kocburak/usenativedriverbug

Screenshots and Videos

Screen_Recording_20250404_190621.mp4
@kocburak
Copy link
Contributor Author

kocburak commented Apr 5, 2025

I tried it on ios there is no issue.

@kocburak kocburak changed the title useNativeDriver:true sets incorrect translate position when moving fast Android - Animated.event useNativeDriver:true sets incorrect translate position when moving fast Apr 8, 2025
@kocburak
Copy link
Contributor Author

kocburak commented Apr 8, 2025

I looked the value usingdisclaimerTranslateY.addListener(value => { console.log(value) }) and the values were correct even though the placement on the screen was wrong. If you need more clarification about the topic I am willing to help.

@kocburak
Copy link
Contributor Author

kocburak commented Apr 8, 2025

I narrowed it down to: Animated.diffClamp function. When I remove this line there is no issue regarding the useNativeDriver:true

@kocburak
Copy link
Contributor Author

kocburak commented Apr 8, 2025

When I looked into DiffClampAnimatedNode.kt file I noticed val animatedNode = nativeAnimatedNodesManager.getNodeById(inputNodeTag) line. Is it possible that we are reading from wrong Tag ?

@kocburak
Copy link
Contributor Author

kocburak commented Apr 10, 2025

@react-native-bot why are you ignoring me :(
@cortinico Sorry for direct mention but even the bot ignored this issue 😄. Is there anything I should look into more?

@cortinico cortinico added Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. and removed Needs: Triage 🔍 labels Apr 11, 2025
@cortinico
Copy link
Contributor

I don't have an exact answer for this one. I believe this is related to an issue we had with Animated + transforms which is still unresolved. @cipolleschi do you have more context or a issue number to link here?

@kocburak
Copy link
Contributor Author

I found couple of issues but couldn't find any workaround.

#10174 : Suggest to use shouldComponentUpdate = () => false But I couldn't figure out how in my TypeScript with function components.
GeekyAnts/NativeBase#334 : No response
#10663 : This is a fix for iOS. I do not have an issue on iOS. Is this fix portable to Android ?

@cipolleschi
Copy link
Contributor

I don't have more context on this. @kocburak here you mentioned:

I narrowed it down to: Animated.diffClamp function. When I remove this line there is no issue regarding the useNativeDriver:true

What line are you referring to?

When I looked into DiffClampAnimatedNode.kt file I noticed val animatedNode = nativeAnimatedNodesManager.getNodeById(inputNodeTag) line. Is it possible that we are reading from wrong Tag ?

It could be but it is unlikely.

About: #50496 (comment)

@kocburak
Copy link
Contributor Author

kocburak commented Apr 14, 2025

In my Reproducer, all my animation logic is as follows:

//Buggy code.
const scrollY = useRef(new Animated.Value(0));

  const handleScroll = Animated.event(
    [{ nativeEvent: { contentOffset: { y: scrollY.current } } }],
    { useNativeDriver: true }
  );

  const minusScrollY = Animated.multiply(scrollY.current, -0.1);
   const stickyTranslateY = Animated.diffClamp(scrollY, -headerHeight, 0);

  let stickyStyles: StyleProp<ViewStyle> = {
    transform: [{ translateY: stickyTranslateY , }]
  }

This is the logic of 1 scroll. Bug still can be reproduce with this much. When I changed it to:

//Working code.
const scrollY = useRef(new Animated.Value(0));

  const handleScroll = Animated.event(
    [{ nativeEvent: { contentOffset: { y: scrollY.current } } }],
    { useNativeDriver: true }
  );

  const minusScrollY = Animated.multiply(scrollY.current, -0.1);
  //const stickyTranslateY = Animated.diffClamp(minusScrollY, -headerHeight, 0);  // <- commented out

  let stickyStyles: StyleProp<ViewStyle> = {
    transform: [{ translateY: minusScrollY }] // <- changed the argument from stickyTranslateY to minusScrollY 
  }

There is no animation bug (notice the comment on const minusScrollY = Animated.diffClamp(minusScrollY, -headerHeight, 0);. Also I tried to comment out multply and leave it out the Animated.diffClamp like this:

//Buggy code.
  const scrollY = useRef(new Animated.Value(0));

  const handleScroll = Animated.event(
    [{ nativeEvent: { contentOffset: { y: scrollY.current } } }],
    { useNativeDriver: true }
  );

  //const minusScrollY = Animated.multiply(scrollY.current, -0.1);   // <- commented out
  const stickyTranslateY = Animated.diffClamp(scrollY.curent, -headerHeight, 0); // <- changed the argument from minusScrollY to scrollY.curent

  let stickyStyles: StyleProp<ViewStyle> = {
    transform: [{ translateY: stickyTranslateY }] 
  }

The issue came back.

Edit: scrollY.current.interpolate can also be removed so i did in this post.

@kocburak
Copy link
Contributor Author

That is how I figured Animated.diffClamp causing the problem

@kocburak
Copy link
Contributor Author

@cortinico I saw this #50716 issue and tried #50496 (comment) with "newArchEnabled": false and no issue. Whatever the problem is, it is related to new Architecture of React Native.

I would like to continue to use new Arch. We are using JNI Turbo Module for some performance improvements. When I tried old arch on my app, it didn't like it 😄 (didn't compile at all).

@kocburak
Copy link
Contributor Author

I am trying to debug this. "DiffClampAnimatedNode.kt" has "prettyPrint" function. How can I enbale it so that I can see when the value changes ?

@sarthak-cars24
Copy link

I have been seeing the same issue after upgrading to React Native v0.76.8. Is their any workaround for this for the time being? Converting all off the codebase to use reanimated just because of this does not make sense, but it has become a release blocker for us.

@cipolleschi cipolleschi added the Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules) label Apr 24, 2025
@cipolleschi
Copy link
Contributor

We don't have any update on this currently, but thank to @kocburak for the thorough investigation.
There might be a bug in the Animated.diffClamp implementation, we need to further investigate it.

I am trying to debug this. "DiffClampAnimatedNode.kt" has "prettyPrint" function. How can I enbale it so that I can see when the value changes ?

@cortinico do you know how to enable it?

@cortinico In general, if you want to debug android, you need to build React Native from source as Android apps use a prebuild version of React Native, so modifying the files in the node_modules folder will not make any visible change in the executed code.

@cortinico
Copy link
Contributor

@cortinico do you know how to enable it?

It's already enabled. It prints on adb logcat here:

@kocburak
Copy link
Contributor Author

kocburak commented Apr 24, 2025

Hi @sarthak-cars24 Unfortunetly I couldn't find a solution. I tried to re do the same animation in reanimated. It worked but then I find out when I import the reanimated package, other pages that uses the safe-area-context package is broken. Whatever I tried the layout of the app is broken the moment I add the reanimated package. Good luck with yours.

Hi @cipolleschi, I will try it. This bug looks like a race condition between the layers of architecture. Probably one of the layer does not update properly. At least thats what I think. But I am very new in react native so I don't have my hopes up

@kocburak
Copy link
Contributor Author

@cipolleschi I failed spectacularly. I added the lines to android/settings.gradle:

includeBuild('../node_modules/react-native') {
    dependencySubstitution {
        substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid"))
        substitute(module("com.facebook.react:react-native")).using(project(":packages:react-native:ReactAndroid"))
        substitute(module("com.facebook.react:hermes-android")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
        substitute(module("com.facebook.react:hermes-engine")).using(project(":packages:react-native:ReactAndroid:hermes-engine"))
    }
}

It gave the following error:

PS D:\GitHub\AwesomeProject> npm run android

> AwesomeProject@0.0.1 android
> react-native run-android    

info Installing the app...

> Task :react-native:packages:react-native:ReactAndroid:hermes-engine:configureBuildForHermes FAILED

[Incubating] Problems report is available at: file:///D:/GitHub/AwesomeProject/android/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.13/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
38 actionable tasks: 3 executed, 35 up-to-date

info 💡 Tip: Make sure that you have set up your development environment correctly, by running npx react-native doctor. To read more about doctor command visit: https://github.com/react-native-community/cli/blob/main/packages/cli-doctor/README.md#doctor

CMake Error at CMakeLists.txt:64 (project):
  Running

   'nmake' '-?'

  failed with:

   Sistem belirtilen dosyayı bulamıyor


CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':react-native:packages:react-native:ReactAndroid:hermes-engine:configureBuildForHermes'.
> Process 'command 'cmd'' finished with non-zero exit value 1

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 2m 29s
error Failed to install the app. Command failed with exit code 1: gradlew.bat app:installDebug -PreactNativeDevServerPort=8081
CMake Error at CMakeLists.txt:64 (project): Running 'nmake' '-?' failed with: Sistem belirtilen dosyayı bulamıyor CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':react-native:packages:react-native:ReactAndroid:hermes-engine:configureBuildForHermes'. > Process 'command 'cmd'' finished with non-zero exit value 1 * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. > Get more help at https://help.gradle.org. BUILD FAILED in 2m 29s.
info Run CLI with --verbose flag for more details.

I read the lines saying "nmake System could not findt it". So I tried added this PATH to System Variables (I am on Windows 10): C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64 and then it gave the following error where I couldn't figure out a solution.

PS D:\GitHub\AwesomeProject> npm run android

> AwesomeProject@0.0.1 android
> react-native run-android    

info Installing the app...

> Task :react-native:packages:react-native:ReactAndroid:hermes-engine:configureBuildForHermes FAILED

[Incubating] Problems report is available at: file:///D:/GitHub/AwesomeProject/android/build/reports/problems/problems-report.html

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.13/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
54 actionable tasks: 5 executed, 49 up-to-date

info 💡 Tip: Make sure that you have set up your development environment correctly, by running npx react-native doctor. To read more about doctor command visit: https://github.com/react-native-community/cli/blob/main/packages/cli-doctor/README.md#doctor

CMake Error at C:/Users/MONSTER/AppData/Local/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake:69 (message):
  The C compiler

    "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: D:/GitHub/AwesomeProject/node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/CMakeFiles/CMakeTmp

    Run Build Command(s):nmake -f Makefile /nologo cmTC_7fe01\fast &&   "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\nmake.exe"  -f CMakeFiles\cmTC_7fe01.dir\build.make /nologo -L                  CMakeFiles\cmTC_7fe01.dir\build
    Building C object CMakeFiles/cmTC_7fe01.dir/testCCompiler.c.obj
        C:\Users\MONSTER\AppData\Local\Android\Sdk\cmake\3.22.1\bin\cmake.exe -E cmake_cl_compile_depends --dep-file=CMakeFiles\cmTC_7fe01.dir\testCCompiler.c.obj.d --working-dir=D:\GitHub\AwesomeProject\node_modules\react-native\ReactAndroid\hermes-engine\build\hermes\CMakeFiles\CMakeTmp --filter-prefix="Note: including file: " -- C:\PROGRA~1\MICROS~3\2022\COMMUN~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\cl.exe @C:\Users\MONSTER\AppData\Local\Temp\nm924E.tmp
    testCCompiler.c
    Linking C executable cmTC_7fe01.exe
        C:\Users\MONSTER\AppData\Local\Android\Sdk\cmake\3.22.1\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\cmTC_7fe01.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- C:\PROGRA~1\MICROS~3\2022\COMMUN~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\cmTC_7fe01.dir\objects1.rsp @C:\Users\MONSTER\AppData\Local\Temp\nm929D.tmp
    RC Pass 1: command "rc /fo CMakeFiles\cmTC_7fe01.dir/manifest.res CMakeFiles\cmTC_7fe01.dir/manifest.rc" failed (exit code 0) with the following output:
    Sistem belirtilen dosyayı bulamıyorNMAKE : fatal error U1077: 'C:\Users\MONSTER\AppData\Local\Android\Sdk\cmake\3.22.1\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\cmTC_7fe01.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- C:\PROGRA~1\MICROS~3\2022\COMMUN~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\cmTC_7fe01.dir\objects1.rsp @C:\Users\MONSTER\AppData\Local\Temp\nm929D.tmp' : return code '0xffffffff'
    Stop.
    NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\nmake.exe"  -f CMakeFiles\cmTC_7fe01.dir\build.make /nologo -L                  CMakeFiles\cmTC_7fe01.dir\build' : return code '0x2'
    Stop.





  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:64 (project)



FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':react-native:packages:react-native:ReactAndroid:hermes-engine:configureBuildForHermes'.
> Process 'command 'cmd'' finished with non-zero exit value 1

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 46s
error Failed to install the app. Command failed with exit code 1: gradlew.bat app:installDebug -PreactNativeDevServerPort=8081
CMake Error at C:/Users/MONSTER/AppData/Local/Android/Sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake:69 (message): The C compiler "C:/Program Files/Microsoft Visual 
Studio/2022/Community/VC/Tools/MSVC/14.43.34808/bin/Hostx64/x64/cl.exe" is not able to compile a simple test program. It fails with the following output: Change Dir: D:/GitHub/AwesomeProject/node_modules/react-native/ReactAndroid/hermes-engine/build/hermes/CMakeFiles/CMakeTmp Run Build Command(s):nmake -f Makefile /nologo cmTC_7fe01\fast && "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\nmake.exe" -f CMakeFiles\cmTC_7fe01.dir\build.make /nologo -L CMakeFiles\cmTC_7fe01.dir\build Building C object CMakeFiles/cmTC_7fe01.dir/testCCompiler.c.obj C:\Users\MONSTER\AppData\Local\Android\Sdk\cmake\3.22.1\bin\cmake.exe -E cmake_cl_compile_depends --dep-file=CMakeFiles\cmTC_7fe01.dir\testCCompiler.c.obj.d --working-dir=D:\GitHub\AwesomeProject\node_modules\react-native\ReactAndroid\hermes-engine\build\hermes\CMakeFiles\CMakeTmp --filter-prefix="Note: including file: " -- C:\PROGRA~1\MICROS~3\2022\COMMUN~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\cl.exe @C:\Users\MONSTER\AppData\Local\Temp\nm924E.tmp testCCompiler.c Linking C executable cmTC_7fe01.exe C:\Users\MONSTER\AppData\Local\Android\Sdk\cmake\3.22.1\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\cmTC_7fe01.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- C:\PROGRA~1\MICROS~3\2022\COMMUN~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\cmTC_7fe01.dir\objects1.rsp @C:\Users\MONSTER\AppData\Local\Temp\nm929D.tmp RC Pass 1: command "rc /fo CMakeFiles\cmTC_7fe01.dir/manifest.res CMakeFiles\cmTC_7fe01.dir/manifest.rc" failed (exit code 0) with the following output: Sistem belirtilen dosyayı bulamıyorNMAKE : fatal error U1077: 'C:\Users\MONSTER\AppData\Local\Android\Sdk\cmake\3.22.1\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\cmTC_7fe01.dir --rc=rc --mt=CMAKE_MT-NOTFOUND --manifests -- C:\PROGRA~1\MICROS~3\2022\COMMUN~1\VC\Tools\MSVC\1443~1.348\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\cmTC_7fe01.dir\objects1.rsp @C:\Users\MONSTER\AppData\Local\Temp\nm929D.tmp' : return code '0xffffffff' Stop. NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.43.34808\bin\Hostx64\x64\nmake.exe" -f CMakeFiles\cmTC_7fe01.dir\build.make /nologo -L CMakeFiles\cmTC_7fe01.dir\build' : return code '0x2' Stop. CMake will not be able to correctly generate this project.
Call Stack (most recent call first): CMakeLists.txt:64 (project) FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':react-native:packages:react-native:ReactAndroid:hermes-engine:configureBuildForHermes'. > Process 'command 'cmd'' finished with non-zero exit value 1 * Try: > Run with --stacktrace option to get the stack trace. > Run with --info or --debug option to get more log output. > Run with --scan to get full insights. > Get more help at https://help.gradle.org. BUILD FAILED in 46s.
info Run CLI with --verbose flag for more details.

Do you have any comment on this ? What am I doing wrong ?

@cortinico
Copy link
Contributor

Do you have any comment on this ? What am I doing wrong ?

That's because build from source doesn't work well with your Windows setup. For build form source on Android, we recommend to use either Linux or Mac machines

@kocburak
Copy link
Contributor Author

kocburak commented May 8, 2025

I gave up. I upgraded my project to React Native 0.79 and retried react-native-reanimated. The layout issues I had with RN 0.77 is gone. Probably it was related to Androids Edge-To-Edge thing. I am adding yet another dependency. I will also test it with iOS and than ship it.

@kocburak
Copy link
Contributor Author

kocburak commented May 19, 2025

Curiosity got the better of me and bought an Mac Mini. I added System.out.println("TestBurak: " + prettyPrint()); in update() function atDiffClampAnimatedNode.kt and it became this:

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.facebook.react.animated

import com.facebook.react.bridge.JSApplicationCausedNativeException
import com.facebook.react.bridge.ReadableMap
import kotlin.math.max
import kotlin.math.min

internal class DiffClampAnimatedNode(
    config: ReadableMap,
    private val nativeAnimatedNodesManager: NativeAnimatedNodesManager
) : ValueAnimatedNode() {
  private val inputNodeTag: Int
  private val minValue: Double
  private val maxValue: Double
  private var lastValue: Double = 0.0

  init {
    inputNodeTag = config.getInt("input")
    minValue = config.getDouble("min")
    maxValue = config.getDouble("max")
    nodeValue = lastValue
  }

  override fun update() {
    val value = inputNodeValue
    val diff = value - lastValue
    lastValue = value
    nodeValue = min(max(nodeValue + diff, minValue), maxValue)


    System.out.println("TestBurak: " + prettyPrint()); // <- Inserted Log

  }

  private val inputNodeValue: Double
    get() {
      val animatedNode = nativeAnimatedNodesManager.getNodeById(inputNodeTag)
      if (animatedNode == null || animatedNode !is ValueAnimatedNode) {
        throw JSApplicationCausedNativeException(
            "Illegal node ID set as an input for Animated.DiffClamp node")
      }
      return animatedNode.getValue()
    }

  override fun prettyPrint(): String =
      "DiffClampAnimatedNode[$tag]: InputNodeTag: $inputNodeTag min: $minValue " +
          "max: $maxValue lastValue: $lastValue super: ${super.prettyPrint()}"
}

And the logs are like this:

2025-05-19 18:43:01.420 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: 0.0 super: ValueAnimatedNode[19]: value: 0.0 offset: 0.0
2025-05-19 18:43:01.515 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -0.761904776096344 super: ValueAnimatedNode[19]: value: -0.761904776096344 offset: 0.0
2025-05-19 18:43:01.521 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -8.0 super: ValueAnimatedNode[19]: value: -8.0 offset: 0.0
2025-05-19 18:43:01.529 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -19.047618865966797 super: ValueAnimatedNode[19]: value: -19.047618865966797 offset: 0.0
2025-05-19 18:43:01.537 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -32.380950927734375 super: ValueAnimatedNode[19]: value: -32.380950927734375 offset: 0.0
2025-05-19 18:43:01.545 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -43.80952453613281 super: ValueAnimatedNode[19]: value: -43.80952453613281 offset: 0.0
2025-05-19 18:43:01.554 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -54.095237731933594 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.561 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -62.85714340209961 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.570 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -70.85713958740234 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.578 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -76.57142639160156 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.586 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -80.76190185546875 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.596 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -82.66666412353516 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.604 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -84.19047546386719 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.612 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -85.71428680419922 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.620 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -87.23809814453125 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.629 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -88.38095092773438 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.637 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -89.9047622680664 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.644 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -91.04762268066406 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.653 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -91.80952453613281 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.670 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -93.33333587646484 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.678 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -94.0952377319336 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.686 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -95.23809814453125 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.694 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -96.38095092773438 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.703 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -97.52381134033203 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.711 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -98.28571319580078 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.719 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -99.04762268066406 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.728 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -100.19047546386719 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.737 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -100.57142639160156 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.745 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -100.95237731933594 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.752 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -101.33333587646484 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.761 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -101.71428680419922 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.769 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -102.0952377319336 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:01.802 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -102.47618865966797 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.415 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -102.85713958740234 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.448 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -103.61904907226562 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.466 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -104.0 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.473 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -104.38095092773438 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.481 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -104.76190185546875 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.499 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -105.14286041259766 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.506 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -105.52381134033203 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.539 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -106.28571319580078 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.572 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -106.66666412353516 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.580 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -107.04762268066406 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0
2025-05-19 18:43:05.614 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[19]: InputNodeTag: 17 min: -49.904762268066406 max: 0.0 lastValue: -107.42857360839844 super: ValueAnimatedNode[19]: value: -49.904762268066406 offset: 0.0

When I let go of the scroll, the bug accours. But there is no log that indicates a faulty behaviour. Both super: ValueAnimatedNode[19] and DiffClampAnimatedNode[19] has the correct values. So problem probably accours else where. Bug accours when I let go of my finger after interrupting momentum scroll. Is hermes have another place where handles the touch event ? And scroll event overrides the Animated values ?

So I added to onTouchEvent of ReactScrollView:

 public boolean onTouchEvent(MotionEvent ev) {
    //..bla bla
    if (action == MotionEvent.ACTION_UP && mDragging) {
      //..bla bla
      System.out.println("TestBurak: Hello From ReactScrollView Finger Up");
    }
   //..bla bla
  }

And it confirmed there was no TestBurak: DiffClampAnimatedNode[19]log from Animated nodes after TestBurak: Hello From ReactScrollView Finger Up and the UI is changed to buggy state. So when the finger up event accours, something else updates the UI other than AnimatedNodes. Any idea on what that might be @cortinico ?

@kocburak
Copy link
Contributor Author

kocburak commented May 19, 2025

I commented out the handlePostTouchScrolling(Math.round(velocityX), Math.round(velocityY)); part on com/facebook/react/views/scroll/ReactScrollView.java and the problem solved 😄 So I re-activated the code and went inside of handlePostTouchScrolling(int velocityX, int velocityY) part on com/facebook/react/views/scroll/ReactScrollView.java and the problem also fixed when I commented out nativeAnimated.userDrivenScrollEnded(ReactScrollView.this.getId());

So of cource I added a log in com/facebook/react/animated/NativeAnimatedModule.java to see which nodes are called:

    for (Integer tag : tags) {
      tagsArray.pushInt(tag);
      System.out.println("TestBurak : " + tag);
    }

Also added logs to see orginal tags of nodes in java/com/facebook/react/animated/NativeAnimatedNodesManager.java

    while (!nodesQueue.isEmpty()) {
      AnimatedNode nextNode = nodesQueue.poll();
      try {
        // NULLSAFE_FIXME[Nullable Dereference]
        nextNode.update();

        System.out.println("TestBurak: " + nextNode.prettyPrint());

Resulting logs is this:

2025-05-19 19:24:29.319 16531-16531 System.out              com.awesomeproject                   I  TestBurak: ValueAnimatedNode[338]: value: 1092.952392578125 offset: 0.0
2025-05-19 19:24:29.319 16531-16531 System.out              com.awesomeproject                   I  TestBurak: InterpolationAnimatedNode[346] super: {super.prettyPrint()}
2025-05-19 19:24:29.319 16531-16531 System.out              com.awesomeproject                   I  TestBurak: MultiplicationAnimatedNode[347]: input nodes: [I@cb87504 - super: ValueAnimatedNode[347]: value: -1092.952392578125 offset: 0.0
2025-05-19 19:24:29.319 16531-16531 System.out              com.awesomeproject                   I  TestBurak: DiffClampAnimatedNode[349]: InputNodeTag: 347 min: -49.904762268066406 max: 0.0 lastValue: -1092.952392578125 super: ValueAnimatedNode[349]: value: -24.761940002441406 offset: 0.0
2025-05-19 19:24:29.319 16531-16531 System.out              com.awesomeproject                   I  TestBurak: TransformAnimatedNode[350]: transformConfigs: [com.facebook.react.animated.TransformAnimatedNode$AnimatedTransformConfig@3493aed]
2025-05-19 19:24:29.319 16531-16531 System.out              com.awesomeproject                   I  TestBurak: StyleAnimatedNode[351] mPropMapping: {transform=350}
2025-05-19 19:24:29.319 16531-16531 System.out              com.awesomeproject                   I  TestBurak: PropsAnimatedNode[352] connectedViewTag: 5058 propNodeMapping: {style=351} propMap: {transform=[{translateY=-25.523780822753906}]}
2025-05-19 19:24:29.432 16531-16531 System.out              com.awesomeproject                   I  TestBurak: Hello From ReactScrollView Finger Up
2025-05-19 19:24:29.509 16531-16531 System.out              com.awesomeproject                   I  TestBurak : 346
2025-05-19 19:24:29.509 16531-16531 System.out              com.awesomeproject                   I  TestBurak : 5068

So this final nativeAnimated.userDrivenScrollEnded(ReactScrollView.this.getId()); call emits the onUserDrivenAnimationEnded event to InterpolationAnimatedNode and some other node of 5068. I have no idea what I am doing. So any direction to look for is appreciated ?

@kocburak
Copy link
Contributor Author

I forcefully removed the InterpolationAnimatedNode from array using:

     for (Integer tag : tags) {
      tagsArray.pushInt(tag);
      System.out.println("TestBurak : " + tag);
      break;
    }

And the bug still accoured. So the problem is due to the unkown node of 5068. My guess is what ever this node is, it calculates the final position of the scroll and sets it to UI and overriding the animated value.

facebook-github-bot pushed a commit that referenced this issue May 19, 2025
Summary:
I noticed a missing debugging text while working on #50496. It was a typo. I though I might as well send a PR.

## Changelog:

[Android] [Fixed] - Fixing a typo in InterpolationAnimatedNode for debug text.

<!-- Help reviewers and the release process by writing your own changelog entry.
Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

Pull Request resolved: #51460

Reviewed By: cortinico, shwanton

Differential Revision: D75005096

Pulled By: javache

fbshipit-source-id: 390452b2b0c6eabfa003b9c95719649c79444d3a
@kocburak kocburak changed the title Android - Animated.event useNativeDriver:true sets incorrect translate position when moving fast Android - Animated.event useNativeDriver:true sets incorrect translate position when scrolling interrupted by user May 19, 2025
@kocburak
Copy link
Contributor Author

kocburak commented May 19, 2025

I did more test and I was wrong. I removed all of this part:

    for (Integer tag : tags) {
      tagsArray.pushInt(tag);
    }

and bug still occurred. When I commented out reactApplicationContext.emitDeviceEvent("onUserDrivenAnimationEnded", onAnimationEndedData); line, bug was fixed. So it seems the problem is entirely somewhere else and not about the nodes at all.

I checked the src/private/animated/createAnimatedPropsHook.jsand chaneg the line 76-81 with this:

 NativeAnimatedHelper.nativeEventEmitter.addListener(
            'onUserDrivenAnimationEnded',
            data => {
              console.log("TestBurak createAnimatedPropsHook")
              node.update();
            },
          );

And this called only once. And again deleting the node.update(); solved it. I traced it to this line 129-138 on src/private/animated/createAnimatedPropsHook.js:

 if (node.__isNative) {
            // Check 2: this is an animation driven by native.
            // In native driven animations, this callback is only called once the animation completes.
            if (isFabricNode) {
              // Call `scheduleUpdate` to synchronise Fiber and Shadow tree.
              // Must not be called in Paper.
              scheduleUpdate();
              console.log("TestBurak: Where am I?"); //<- added log
            }
            return;
          }

This log also triggered once and removing scheduleUpdate(); solved the issue. Now I don't know where to go or is this the solution ? Maybe on finger Up event scheduleUpdate shouldn't have been trigger ? @cortinico @cipolleschi Any commet on this ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules)
Projects
None yet
Development

No branches or pull requests

4 participants