facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
119.56k stars 24.37k forks source link

[Android][Animation] Interpolated translateY value causes android view to jump. #21801

Open mmamoyco opened 6 years ago

mmamoyco commented 6 years ago

Environment

React Native Environment Info: System: OS: macOS 10.14 CPU: x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz Memory: 862.68 MB / 16.00 GB Shell: 3.2.57 - /bin/sh Binaries: Node: 10.9.0 - ~/.nvm/versions/node/v10.9.0/bin/node Yarn: 1.10.1 - ~/.nvm/versions/node/v10.9.0/bin/yarn npm: 6.2.0 - ~/.nvm/versions/node/v10.9.0/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman SDKs: iOS SDK: Platforms: iOS 11.2, macOS 10.13, tvOS 11.2, watchOS 4.2 IDEs: Android Studio: 3.1 AI-173.4819257 Xcode: 9.2/9C40b - /usr/bin/xcodebuild npmPackages: react: 16.6.0-alpha.8af6728 => 16.6.0-alpha.8af6728 react-native: ^0.57.3 => 0.57.3 npmGlobalPackages: react-native-cli: 2.0.1

Description

I'm trying to implement collapsible header using React Native Animated API. using event method i get AnimatedHeaderValue and interpolate it into translateY value. This value i apply to container of my listView (so listView moves vertically). IOS animation works perfectly, but Android animation jumping and lagging when i scroll. I tried to inscrease scroll value and Android animation became more smooth.

This is scrollView container that passes onScroll to scrollView (listView)

<ScCompanyNewsFeedList optimizeHeight getRef={scrollView => { console.log("SCROLL VIEW", scrollView) this._scrollView = scrollView; }} scrollEventThrottle = { 2 } onScroll={Animated.event( [{ nativeEvent: { contentOffset: { y: this.AnimatedHeaderValue }}}], )} companyId={this.props.companyId}/> }

this is base container that contains tabs and my scrollView. It's moving when scroll.

<Animated.View style={[{flex: 1}, {transform: [{translateY: headerHeight}]}]}> ... </Animated.View>

Interpolation

const animationRange = this.AnimatedHeaderValue.interpolate({ inputRange: [0, scrollRange], outputRange: [0, 1], extrapolate: "clamp" }); const headerHeight2 = animationRange.interpolate({ inputRange: [0, 1], outputRange: [0, -200] });

react-native-bot commented 6 years ago

It looks like you are using an older version of React Native. Please update to the latest release, v0.57 and verify if the issue still exists.

The ":rewind:Old Version" label will be removed automatically once you edit your original post with the results of running react-native info on a project using the latest release.

mmamoyco commented 6 years ago

The issue still exists on rn 0.57

darylalexjohnson commented 5 years ago

@godofmadness You ever resolve this issue?

mmamoyco commented 5 years ago

@darylalexjohnson nope, issue still exist.

lindesvard commented 5 years ago

Having similar issues..

d2dindustries commented 5 years ago

I am also having this issue. Any resolution in sight?

My guess is that Y translating the scrollview while scrolling throws off the difference calculation between the start scrollY coordinate and it's relative current scrollY coordinate. I assume this calculation is how the scrollview component does it's scrolling animation. If it's relative point is changing along with the y translation, that would explain the jumping.

mateusfontana commented 5 years ago

I'm also having this issue using RN 0.57.8.

It looks like it only happens when you have a decreasing outputRange, like [100, 0], or in OP's case, [0, -200]. It also happens with animated margins and paddings.

kelset commented 5 years ago

Does this still happen on 0.58?

mateusfontana commented 5 years ago

@kelset Yes. Here is a example tested on RN 58.1:

import React, { Component } from "react";
import { Animated, View, StyleSheet } from "react-native";

export default class Example extends Component {
  state = {
    scrollY: new Animated.Value(0)
  };

  render() {
    const marginTopAnimated = this.state.scrollY.interpolate({
      inputRange: [0, 100],
      outputRange: [100, 0],
      extrapolate: "clamp"
    });

    return (
      <View style={{ flex: 1, backgroundColor: "skyblue" }}>
        <Animated.ScrollView
          style={[
            styles.scrollView,
            {
              transform: [{ translateY: marginTopAnimated }]
            }
          ]}
          scrollEventThrottle={16}
          onScroll={Animated.event(
            [
              {
                nativeEvent: { contentOffset: { y: this.state.scrollY } }
              }
            ],
            { useNativeDriver: true }
          )}
        >
          <View style={{ height: 1000 }} />
        </Animated.ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  scrollView: {
    backgroundColor: "#FFF",
    borderTopRightRadius: 28,
    borderTopLeftRadius: 28
  }
});

Just create a new project with react-native init and paste it on App.js. Here is a gif of the result:

example-animation

benevbright commented 5 years ago

Hi, I'm maintaining react-navigation-collapsible. This issue is critical for my module and I tried many things for a workaround but no luck.

benevbright commented 5 years ago

https://github.com/facebook/react-native/issues/15445 It has not been fixed for a long time though.

kelset commented 5 years ago

Are there any PRs open to try and fix this? Or commits already on master?

benevbright commented 5 years ago

Can anyone tell me how to trigger re-compile react-native Android native? I want to try modifying some files. But It seems that it's using a build from somewhere else. ./gladlew clean nor deleting android/app/build do not work. Even I created a new project and deleted a couple of native java file just to break building, but it succeeds to build the project!

davidkalosi commented 5 years ago

any news on this issue, it's a pretty annoying and visually nasty bug

thx

httol commented 5 years ago

I think this is a serious issue, but nobody has any solution,hahah

d2dindustries commented 5 years ago

Is anyone looking into this?

stockrel commented 5 years ago

+1

ddedic commented 5 years ago

+1

imyagnesh commented 5 years ago

+1

davidkalosi commented 5 years ago

bump again, can we get at least a milestone / time frame when this will be addressed?

alz10 commented 5 years ago

1 Eternity Later...............

This bug still exists on v0.59

kelset commented 5 years ago

can we get at least a milestone / time frame when this will be addressed?

AFAIK this issue is not in the roadmap - the best idea would be for someone actually concerned with this issue to investigate it more and submit a PR. A lot of work has been done to improve the PR to master timing so that would be the best way.

We are currently re-thinking how to approach issues so maybe in the next few days someone will be able to pick this up - but, again, since you are experiencing the issue you may have more time to dedicate to it.

re: @benevbright sorry just saw your question:

Can anyone tell me how to trigger re-compile react-native Android native?

There is a section in the docs about building from source -> https://facebook.github.io/react-native/docs/building-from-source

alz10 commented 5 years ago

@benevbright Hello, I started using your react-navigation-collapsible unfortunately the bug on android where the header started to jump when scrolling slowly made it not suitable for production release. I made a hack way to avoid the "jumping bug" but i dont how to implement it on your library but i hope it helps

https://snack.expo.io/r1hwBv0wV - Here's the one with "Jumping Bug" https://snack.expo.io/Hk34BPCDN - Here's the one without the bug

I just add the following style

position: 'absolute',
zIndex: 999,
top: 0

i dont know but i think the position: 'absolute' removes the bug

brunohkbx commented 5 years ago

Any update on this?

belgamo commented 5 years ago

+1

alz10 commented 5 years ago

They dont give a sh*t anymore to this bug. This is the reason why some RN devs are going flutter.

brunohkbx commented 5 years ago

Hey @kelset, how much time until Mid-Priority issues get fixed?

kelset commented 5 years ago

I don't know, as I mentioned previously:

AFAIK this issue is not in the roadmap - the best idea would be for someone actually concerned with this issue to investigate it more and submit a PR. A lot of work has been done to improve the PR to master timing so that would be the best way.

Also, we are trying to focus on getting an RC for 0.60 out this week, so 🤞, maybe it's fixed on master?

wuchangming commented 5 years ago

@AaaChiuuu , I think it‘s not a good workaround. Demo without the bug just because header layout Animation do not affect the scrollview.
https://snack.expo.io/@wuchangming/bad-donut-x

alishamae commented 5 years ago

Unsubscribe

On Mon, May 27, 2019, 9:33 PM wuchangming notifications@github.com wrote:

@AaaChiuuu https://github.com/AaaChiuuu , I think it‘s not a good workaround. Demo without the bug just because header layout Animation do not affect scrollview. https://snack.expo.io/@wuchangming/bad-donut-x

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/facebook/react-native/issues/21801?email_source=notifications&email_token=AMDLXR7PCPTSA7JG2ACPZWLPXSDWTA5CNFSM4F3TABE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWKXCLQ#issuecomment-496333102, or mute the thread https://github.com/notifications/unsubscribe-auth/AMDLXR6HQNBPNOT544GQFSLPXSDWTANCNFSM4F3TABEQ .

HarshitMadhav commented 5 years ago

@kelset I am using 0.59.8 version. This issue still persists. Is it fixed in 0.60?

HarshitMadhav commented 5 years ago

In react-native version 0.64.0 this issue has been resolved as this commit has been merged to the master https://github.com/facebook/react-native/commit/f954f3d9b674b13977f722bc3b8dc6c1b99fe6c7

wenkangzhou commented 5 years ago

Has any idea for below 0.60.4?

alz10 commented 5 years ago

@HarshitMadhav react-native version 0.64.0? you mean 0.60.4....?

The bug still persist on RN v0.60.4

HarshitMadhav commented 5 years ago

@Albert0405 read out this comment https://github.com/react-native-community/releases/issues/130#issuecomment-519191161

HarshitMadhav commented 5 years ago

I referenced this issue to the react-native latest discussions and got to know that this has been resolved in react-native version 0.64.4 refer here https://github.com/react-native-community/releases/issues/130#issuecomment-519191161

brunohkbx commented 5 years ago

cc @benevbright

benevbright commented 5 years ago

I just tried the latest RN, 0.60.5. But the issue is still happening.

Feel free to try this example. https://github.com/benevbright/react-navigation-collapsible/tree/master/example

GIF

Aug-18-2019 6-19-48 PM

sunnylqm commented 5 years ago

@HarshitMadhav That commit had been merged since 0.47. image image

Why do you think that old commit is related to this issue?

benevbright commented 5 years ago

Ok, I guess we totally misunderstood. Thanks! @sunnylqm

HarshitMadhav commented 5 years ago

@sunnylqm Yeah, I think we totally misunderstood these commits. Thanks!

SathishSaminathan commented 5 years ago

Anyone has solution?

nidorx commented 5 years ago

@benevbright, I'm implementing an application to document a component library I own.

In the app, the header is animated and I went through the same problem described here.

To solve the problem, I made the following adjustments to my component.

1 . Additional content is passed through the page to NavigationHeader via props

  1. NavigationHeader looks at content height and tells page about new size
  2. The page, which has ScrollView (or SectionList and etc), renders an empty element with this height received (a padding at the top), so the page does not use "transform: [{translateY: translateY} animation ] "(which is the source of the problem)
  3. On the page, another aesthetic adjustment was to remove the vertical scroll bars (showsVerticalScrollIndicator = {false}). In the future I intend to create a virtual scroll bar, just to allow the visual response to the user about the screen position, discounting the height of the empty component.

The implementation files (and most important lines) are:

Below are two videos with the result, (you can also run the application https://github.com/nidorx/rn-components-ui/tree/master/example and see the result [still under development] for yourself)

AnimationHeader - https://youtu.be/IyThm01At1g

Page padding top - https://youtu.be/kNwCq6xYEHQ

ezgif com-optimize

benevbright commented 5 years ago

@nidorx Hi, Thanks for the comment. Nice workaround.

But your solution is off the topic. Because you don't use translateY on ScrollView but gave top margin and translate "Header".

This bug is about using translateY on ScrollView.

nidorx commented 5 years ago

@nidorx Hi, Thanks for the comment. Nice workaround.

But your solution is off the topic. Because you don't use translateY on ScrollView but gave top margin and translate "Header".

This bug is about using translateY on ScrollView.

...so the page does not use "transform: [{translateY: translateY} animation ] "(which is the source of the problem)

It is not offtopic in reality, in the previous implementation I suffered from the same problem described, to solve the problem, I stopped using translateY and started using a padding at the top.

benevbright commented 5 years ago

@nidorx Yes, I understood. But what I’m saying is that it’s a workaround. And here we want this bug will be fixed so we can use translateY on ScrollView.

FrancoisDeBellescize commented 5 years ago

Hi ! Is there any update ? I'm using expo SDK 35 so RN 0.59.8 and we still have this problem using transform: [{ translateY: contentTranslate }] where contentTranslate is an interpolate() of Animated.Value

carthagan commented 5 years ago

Hi there, The problem seems to be related to the animation range of the interpolate function. There seems to be some kind of "resonance" in the scroll animation for certain relative values. In my case (I am using it to make a header parallax effect), a simple workaround I found was to change the input range : From inputRange: [0,(HEADER_EXPANDED_HEIGHT-HEADER_HALF_HEIGHT)], to inputRange: [0,(HEADER_EXPANDED_HEIGHT-HEADER_HALF_HEIGHT)*1.5], I then put some bottom padding to the Animated.Scrollview component: contentContainerStyle={{paddingBottom: 25}} It is not very clean but it did the trick for me.

benevbright commented 5 years ago

I ended up to look into RN android.

https://github.com/facebook/react-native/issues/15445#issuecomment-326680200

@janicduplessis You pointed the place out where this bug started. Could you help us?

benevbright commented 4 years ago

@kelset @janicduplessis @sahrens

https://github.com/facebook/react-native/blob/0ef0d3167e291f31ce01ceb729df77cc679d2330/ReactAndroid/src/main/java/com/facebook/react/views/scroll/OnScrollDispatchHelper.java#L39

We need to compose the current translateY value here. Do you know how to get the android ScrollView's transitionY?

I tried using every member getter like this.getTransitionY() but couldn't get desired value.