When using FlatList with inverted={true} the scrolling doesn't work as expected.
it seems that the momentum is not inverted, and at the end of the scroll - the momentum takes it back to the other side
Environment:
OS: macOS High Sierra 10.13.4
Node: 8.11.1
Yarn: 1.5.1
npm: 5.6.0
Watchman: 4.9.0
Xcode: Xcode 9.3 Build version 9E145
Android Studio: 3.1 AI-173.4670197
Packages: (wanted => installed)
react: 16.3.1 => 16.3.1
react-native: ~0.55.2 => 0.55.4
With Android P public beta installed -
https://snack.expo.io/BklXgV8Nk7
scrolling will work as usual
momentum is inverted
For anyone else running into this issue, I could also suggest looking into this library: https://github.com/godness84/react-native-recyclerview-list
It's not my project, but because of this specific issue I've opened a PR for them that allows it to be used in combination with inverted lists: https://github.com/godness84/react-native-recyclerview-list/pull/25~~ Update: The latest release (0.3.4) includes the inverted prop.
Reproducible on release version of Android P
Reproducible also on native android app (example), with scrollView and scaleY=-1
same app don't have the problem on Oreo devices.
so it may be a native issue, and possibly related to this:
https://developer.android.com/about/versions/pie/android-9.0-changes-28#scrolling-element
?
@arendjr that recyclerview-list looks amazing, are you aware of a similar project for iOS?
@enahum No sorry, the catch is indeed it's Android-only. I haven't really looked for iOS counterparts though. Ideally I'd still hope this behavior gets properly fixed in FlatList, of course.
So I've been digging into this a bit more and have landed on this line:
Seems that thevelocityY thats coming in is negative when the FlatList is inverted and you fling to scroll up causing the list to start to scroll up but then shoot back down. Was able to patch the issue by setting velocityY = velocityY * -1; within the if statement. Obviously not a real fix but hopeful that it at least sheds some light on what may be the cause. Going to continue diving in to see if I can chase it down.
@jarredwitt Any luck getting to the bottom of this?
I'd appreciate any help on this 🙇
Opened an issue for Android, since it happens in native apps with scrollView and scaleY=-1
https://issuetracker.google.com/issues/112385925
you can try and star it to let them know it's needed :-)
Our temp solution was to natively inherite scrollView, override onTouchEvent and call fling with the correct velocity when ACTION_UP was called
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (Build.VERSION.SDK_INT >= 28) {
initVelocityTrackerIfNotExists();
_velocityTracker.addMovement(ev);
if (ev.getActionMasked() == ACTION_UP && _dragging) {
_velocityTracker.computeCurrentVelocity(1000, _maximumVelocity);
int velocityY = (int) _velocityTracker.getYVelocity(ev.getPointerId(0));
int velocityX = (int) _velocityTracker.getXVelocity(ev.getPointerId(0));
int scrollY = getScrollY();
if ((Math.abs(velocityY) > _minimumVelocity) && (scrollY > 0 || velocityY > 0) && (scrollY < getScrollRange() || velocityY < 0)) {
fling(velocityY);
}
recycleVelocityTracker();
ReactScrollViewHelper.emitScrollEndDragEvent(this, velocityX, velocityY);
_dragging = false;
return true;
}
}
return super.onTouchEvent(ev);
}
I used a similar workaround to @Rongrs by checking this.getScaleY() < 0 and Build.VERSION in
https://github.com/facebook/react-native/blob/0.54-stable/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java#L270
@Override
public void fling(int velocityY) {
if (mScroller != null) {
// FB SCROLLVIEW CHANGE
// We provide our own version of fling that uses a different call to the standard OverScroller
// which takes into account the possibility of adding new content while the ScrollView is
// animating. Because we give essentially no max Y for the fling, the fling will continue as long
// as there is content. See #onOverScrolled() to see the second part of this change which properly
// aborts the scroller animation when we get to the bottom of the ScrollView content.
int scrollWindowHeight = getHeight() - getPaddingBottom() - getPaddingTop();
if (this.getScaleY() < 0 && Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1) {
velocityY *= -1;
}
mScroller.fling(
getScrollX(),
getScrollY(),
0,
velocityY,
0,
0,
0,
Integer.MAX_VALUE,
0,
scrollWindowHeight / 2);
postInvalidateOnAnimation();
// END FB SCROLLVIEW CHANGE
} else {
super.fling(velocityY);
}
@krishom is this working well for you? I'm trying to test out your code, but can't get it to work. getScaleY always returns 1.0f for me.
@jarredwitt Yeah, my fix is working on a Pixel 2 running Android P. The ScrollView lives in a <SectionList inverted> component. Before discovering the getScaleY() check, I was dispatching a command across the bridge during the SectionList's first onScroll event to notify the ScrollView to invert the fling velocity. This also worked to some extent, but wasn't as clean of a fix.
@krishom interesting. Actually debugging right now and can't get getScaleY to return anything other than 1.0. Can I ask what your targetSdkVersion is set to?
@jarredwitt build.gradle:
targetSdkVersion 27
A workaround that works for us that's far simpler but may not be a viable option for everyone: don't use inverted={true} and instead just reverse the order of the data you are passing to the FlatList.
Just tested locally with 0.57-rc4 and sadly neither of the last two commits by @olegbl seems to have fixed it.
Will try to have someone from the core take a closer look at this since it's something that I fear in a couple months will affect a good portion of Pixel users.
cc @dulmandakh
@kelset I tried to make a workaround as safe as possible and w/o having to check for a build number: https://github.com/facebook/react-native/pull/21117/files
That fixed the issue for us.
I will be happy to hear your feedback!
@Rongrs @jarredwitt @krishom Could you please explain, how are you using overridden ReactScrollView.java class with your app? Are you creating a custom build of react-native .aar file?
Any news on this from the react native team side?
How to apply the changes made for this files?
@roylabanon the easiest way is to use a fork of React Native and apply the patch there.
Having a fork might be useful for other things as well (let's say you need to expose a property that RN doesn't expose by default, etc).
Hi Igor, thanks for the reply, but I'm kind of a newbie in this stuffs, you
got a good step-by-step guide to help me out? Basically i tried to apply
this fix, but it doesn't seem to take effect, so wondering what needs to be
done. Thanks so much.
On Tue, Oct 9, 2018 at 4:38 PM Igor Mandrigin notifications@github.com
wrote:
@roylabanon https://github.com/roylabanon the easiest way is to use a
fork of React Native and apply the patch there.Having a fork might be useful for other things as well (let's say you need
to expose a property that RN doesn't expose by default, etc).—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/19434#issuecomment-428107839,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ANd1uLiuyCwrBfmHZRIMIMkoQ-jMcdZhks5ujGCAgaJpZM4UMcR9
.
@roylabanon You need to build react-native from source in order to make any android changes take effect. Maintaining a fork of react-native isn't as trivial as forking the github repo and commiting your local changes. It always involves an additional building step, at least for android. Good luck.
@roylabanon it isn't super trivial, but that is how we did it.
Here is our RN fork (with the branch containing the fix): https://github.com/status-im/react-native/tree/status-0.56-1
And here is the PR that tweaks all the project settings: https://github.com/status-im/status-react/pull/4981/files
Note, that apart from that you will need to setup your dev environment (install Android NDK, etc), but that is very well described in the official docs (as @johakr mentioned).
@roylabanon it isn't super trivial, but that is how we did it.
Here is our RN fork (with the branch containing the fix): https://github.com/status-im/react-native/tree/status-0.56-1
And here is the PR that tweaks all the project settings: https://github.com/status-im/status-react/pull/4981/filesNote, that apart from that you will need to setup your dev environment (install Android NDK, etc), but that is very well described in the official docs (as @johakr mentioned).
Great thanks so much guys
@kelset I tried to make a workaround as safe as possible and w/o having to check for a build number: https://github.com/facebook/react-native/pull/21117/files
That fixed the issue for us.I will be happy to hear your feedback!
Is there any chance of this PR being merged before the next release?
Following also have this problem 👍
hey sorry, I completely missed all notifications about this lately 🤦♂️
I'll double check the PR and we'll try to get it in asap (but probably won't be next patch for 0.57.x, we'll see - if not it will be in the one after that).
Thanks @kelset - this effect all chat apps and anything that uses inverted={true} on a Flatlist.
Did this fix land in 0.57.5? The PR https://github.com/facebook/react-native/pull/21117 was merged right before the release but I'm crossing my fingers that maybe somehow it sneaked in...
@kelset will be able to tell you if it landed
@scottmas you can check the changelog to know which commits landed and which not.
You can also suggest commits that landed to be cherry picked in the dedicated issue - in particular, this commit has already been requested.
Nope, this fix didnt make into 0.57.3.
@ilevator latest version is 0.57.5
0.57.7 looks like fixed!
Most helpful comment
So I've been digging into this a bit more and have landed on this line:
https://github.com/facebook/react-native/blob/8f7372fe1b8517848b8d35ded2b07c74adb3d574/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java#L265
Seems that the
velocityYthats coming in is negative when the FlatList is inverted and you fling to scroll up causing the list to start to scroll up but then shoot back down. Was able to patch the issue by settingvelocityY = velocityY * -1;within the if statement. Obviously not a real fix but hopeful that it at least sheds some light on what may be the cause. Going to continue diving in to see if I can chase it down.