Summary:
The native module might be null, and that should not be an exception thrown by the subclassed method.
Changelog:
[Android][Internal] - Mark getModule API to be nullable
Reviewed By: mdvacca, makovkastar
Differential Revision: D37900294
fbshipit-source-id: a4ecc9804b95bf0512554e96985f272b435e33b2
Summary:
This diff fixed a NPE in horizontal scroll view when calling scrollToEnd API in side effect.
The problem here is we may trigger side-effects before the required view got mounted for performance reasons. We've been fixing this with retry logic on those side-effects and we've already done this in vertical scroll view. This is to fix on the horizontal scroll as well.
Changelog:
[Android][Fixed] - Fixed HorizontalScrollView API scrollToEnd causing NPE in side-effects.
Reviewed By: lunaleaps, JoshuaGross
Differential Revision: D37571847
fbshipit-source-id: 0a4dc38381008350fd09908aa3ebb64e3e65a424
Summary:
This diff adds an assertion to make sure the pending events are enqueued only when the event emitter is null. This is to avoid unexpected workflow when we queue events but we should just dispatch them.
Changelog:
[Android][Internal] - Make sure we only queue events when event emitter is null
Reviewed By: javache
Differential Revision: D36916482
fbshipit-source-id: fff305615b302ece26bc2482c826b74de4f70266
Summary:
This diff address an edge case when the pending events are enqueued when the surface is stopped. In this case we will reset map that holds view state to null, which will cause NPE.
Changelog:
[Android][Fixed] - Fix edge case when we enqueue a pending event to views on stopped surface
Reviewed By: javache, gorodscy
Differential Revision: D36912786
fbshipit-source-id: 3ae5a4b08a0a6bf55538d69ac80a101c2c3d899a
Summary:
This diff fixed an edge case that event dispatching is failed after pre-allocation of a view and before the view is mounted.
When a cached image is loaded, we will dispatch the event to JS immediately. This is could happen after the view is created during pre-allocation phase, when the event emitter is not instantiated yet. In that case, we will see [an error](https://github.com/facebook/react-native/blob/main/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java#L927) and the event will effectively be ignored.
To fix that we introduced a queue in this diff for those events. They will be dispatched in order when the view is mounted and the event emitter is non-null.
Changelog:
[Android][Fixed] - Fixed an edge case that event dispatching is failed after pre-allocation of a view and before the view is mounted.
Reviewed By: mullender
Differential Revision: D36331914
fbshipit-source-id: cd065b0b36978cb5f0aac793d8d16f07a48f0881
Summary: There's no need to use private feature flag for overflowInset feature. This makes future refactor on feature flags easier.
Reviewed By: javache
Differential Revision: D35866302
fbshipit-source-id: a3fde212ff40cd6d4c68832bb39b34de5a17a8d4
Summary:
The `notifyNativeGestureEnded` API is added to notify user gesture ended, so that any optimization we had during handling the gesture can be restored.
It's possible that when the gesture finishes, the RootView is already unmounted from the native side. This might happen when user starts a gesture that caused leave of the RN screen, or close the app.
Changelog:
[Android][Internal] - Avoid NPE for gesture notifier
Reviewed By: javache
Differential Revision: D35902523
fbshipit-source-id: 9bb5819a53dd053290031eebaae1b8f0318ae534
Summary:
Refactor of TouchTargetHelper.findTargetPathAndCoordinatesForTouch to avoid unnecessary lookup of views during the dispatching of Hover Events
changelog: [internal] internal
Reviewed By: lunaleaps, mdvacca
Differential Revision: D32296003
fbshipit-source-id: 93834c37331ad5d75645a5665a1c8c3d965765fb
Summary:
Adding more context for event dispatching process in systrace.
Changelog: [Internal]
Reviewed By: philIip
Differential Revision: D35208257
fbshipit-source-id: 4a70e15a0074d4a53a895066e6fa1e60a6ebda0d
Summary: This diff adds flag to `ReactRootView` to control if the touch event is to be dispatched to the JS side. This is needed for subclass of `ReactRootView` to control if the dispatch is needed.
Reviewed By: javache
Differential Revision: D35033684
fbshipit-source-id: febab6988cc3e4259e726d03d797dd0ffc978d24
Summary:
The context could be null or is finishing when we create the redbox surface content view. This diff adds the null check and delegate the message in log when context is not available.
Changelog:
[Android][Fixed] - Adding null check for context in redbox surface delegate
Differential Revision: D34930595
fbshipit-source-id: 91508ded7821033abcd893f70bcfe3cc9ee5b5c2
Summary:
When the `snapToOffsets` prop is empty array, the scroll view would crash unexpectly. This diff fixed that by treating empty array prop as null value for `snapToOffsets`.
Changelog:
[Android][Fixed] - Fix crash on empty snapToOffsets array
Reviewed By: makovkastar
Differential Revision: D34802022
fbshipit-source-id: af330512e444081b0cb02b65288ec5cd2bd14205
Summary:
This diff fixed an issue that caused regression in fb4a and React Native panel apps regarding scrolling behavior. When scrolling in either horizontal or vertical scroll view, if the consecutive touch interrupted the previous fling (post touch scrolling), the scroll view would block touch event from dispatching to the content view. Thus, the items in scroll view are not responding to touch events anymore.
The diff that caused this issue is D34627330 (https://github.com/facebook/react-native/commit/0368081858193d7c2537acd9080d11bb701ee98b). In that diff, I added code to cancel the scheduled post touch runnable when touch down is received in scroll view. That is expected as the post touch runnable is to handle snapping scroll case, where [an extra fling](https://fburl.com/code/7qza1ece) is triggered to make sure scroll view stops at the right position. When user touch the screen before the previous scroll fling finishes, this post processing is no longer needed -- the new touch should take full control of scroll view.
However, in D34627330 (https://github.com/facebook/react-native/commit/0368081858193d7c2537acd9080d11bb701ee98b), I failed to reset the runnable instance `mPostTouchRunnable` to null when cancelling it. This caused the future post touch handle logic [stops to run](https://fburl.com/code/lh8pi7l0), as it thinks the runnable is non-null and has been scheduled. This prevents fabric from receiving proper scroll state updates from android side, thus causing a state corruption and affects logic to decide where the scroll offset is and where the child item is after that.
This diff fixed the issue by resetting the runnable instance, as well as making sure if the runnable is already running and the extra fling starts, we are canceling that fling animation properly.
Changelog:
[Android][Fixed] - Fixed regression on content in scroll view not responding to touch when fling got interrupted
Reviewed By: ShikaSD
Differential Revision: D34734129
fbshipit-source-id: 7d7689d203ce76c59cd44e16e31582317bb409bd
Summary:
The issue to be fixed here is an edge case when in nested scroll view, for example vertical scroll wraps horizontal scroll, when user scrolls horizontally then move the joystick downwards, the horizontal scroll would bounce back. This is shown in the demo:
https://pxl.cl/209f8
The root cause of the issue is due to two workflows fight to set the scroll position and confusing the scroll change dispatcher to calculate fling velocity direction, which caused a wrong fling behavior. Check this log and description to get more details:
{F706620839}
To fix the issue, in this diff we overridden the `onInterceptTouchEvent` method in panel app scroll views, and make it return true when the previous scroll is still running. This effectively skips the drag slop in the default scroll view behavior, as we know the touch event should've been handled by the scroll view if it's still scrolling.
This way, the vertical scroll part on the vertical scroll view will not be dispatched to the horizontal scroll at all. This allows the nested scroll view to work separately.
Changelog:
[Android][Internal] - Share the post intercept touch event logic in scroll views
Reviewed By: javache
Differential Revision: D34627329
fbshipit-source-id: d500ec3bfbe349a45ef5c1360b5c8807c168f682
Summary:
This diff aims to fix an issue I found while working on T113264056. It's to address the [comment](https://www.internalfb.com/diff/D3207608 (https://github.com/facebook/react-native/commit/a3146e41a259175f0c79e3c213523a0fb21613d7)?dst_version_fbid=507451319451602&transaction_fbid=1615731455398227) in an old diff D3207608 (https://github.com/facebook/react-native/commit/a3146e41a259175f0c79e3c213523a0fb21613d7). That issue begins to surface after I made the change in the next diff, which is discussed in detail in the task description (T113385381).
The fix here is to cancel the post touch processing when a new touch down is received. This should've cancel any previous post touch processing as the new touch should take full control of scrolling.
Changelog:
[Android][Fixed] - Cancel post touch process when new touch is received
Reviewed By: javache
Differential Revision: D34627330
fbshipit-source-id: 1fb8cfc1a4d94349b5290915a0a9f190186f2af3
Summary:
This diff fixes overflowInset calculation when a shadow node has transform matrix from a transfrom prop in JS. Specifically, this fixed the use case when transform directly used on a view component. When using Animated.View, it will create an invisible wrapper which will behave correctly with existing logic. This diff bring both use cases to work properly.
When a shadow node has transform on it, it will affect the overflowInset values for its parent nodes, but won't affect its own or any of its child nodes overflowInset values. This is obvious for translateX/Y case, but not for scale case. Take a look at the following case:
```
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│Original Layout │ │ Translate AB │ │ Scale AB │
└────────────────┘ └────────────────┘ └────────────────┘
─────▶ ◀───── ─────▶
┌ ─ ─ ─ ┬──────────┐─ ─ ─ ─ ┐ ┌ ─ ─ ─ ┬──────────┐─ ─ ─ ─ ─ ┐ ┌ ─ ─ ─ ─ ─ ┬──────────┐─ ─ ─ ─ ─ ┐
│ A │ │ A │ │ A │
│ │ │ │ │ │ │ │ ├ ─ ─ ─ ─ ─ ┼ ─ ─┌─────┤─ ─ ─ ─ ─ ┤
─ ─ ─ ─│─ ─ ─┌───┐┼ ─ ─ ─ ─ │ │ ◀─ ─ ─ │ │AB │ ─ ─ ─▶
│ │ │AB ││ │ │ ┌ ─ ─ ┼ ─ ─ ─ ┬──┴┬ ─ ─ ─ ─ ┤ │ │ │ │ │
└─────┤ ├┘ └───────┤AB │ └────┤ │
│ │┌──┴─────────┤ │ │ │ │ │ │ │ │ ┌───┴──────────┤
││ABC │ │┌──┴─────────┐ │ │ABC │
│ │└──┬─────────┤ │ │ │ ││ABC │ │ │ │ │ │ │
┌───ABD───────┴─┐ │ │ │└──┬─────────┘ │ ▼ │ └───┬──────────┘
├─────────────┬─┘ │ │ │ │ ├───ABD───────┴─┐ │ │ │ ├────────────────┴──┐ │ │
─ ─ ─ ─ ─ ─ ─└───┘─ ─ ─ ─ ─ ▼ └─────────────┬─┘ │ ▼ │ ABD │ │
└ ┴ ─ ─ ─ ─ ─ ─ ┴───┴ ─ ─ ─ ─ ┘ ├────────────────┬──┘ │ │
─ ─ ─ ─ ─ ─ ─ ─ ┴─────┴ ─ ─ ─ ─ ─
```
For the translate case, only view A has change on the overflowInset values for `right` and `bottom`. Note that the `left` and `top` are not changed as we union before and after transform is applied.
For the scale case, similar things are happening for view A, and both `left`, `right`, and `bottom` values are increased. However, for View AB or any of its children, they only *appear* to be increased, but that is purely cosmetic as it's caused by transform. The actual values are not changed, which will later be converted during render phase to actual pixels on screen.
In summary, overflowInset is affected from child nodes transform matrix to the current node (bottom up), but not from transform matrix on the current node to child nodes (top down). So the correct way to apply transform is to make it only affect calculating `contentFrame` during layout, which collects child nodes layout information and their transforms. The `contentFrame` is then used to decide the overflowInset values for the parent node. The current transform matrix on parent node is never used as it's not affecting overflowInset for the current node or its child nodes.
This diff reflects the context above with added unit test to cover the scale and translate transform matrix.
Changelog:
[Android/IOS][Fixed] - Fixed how we calculate overflowInset with transform matrix
Reviewed By: sammy-SC
Differential Revision: D34433404
fbshipit-source-id: 0e48e4af4cfd5a6dd32a30e7667686e8ef1a7004
Summary:
This diff adds `RedBoxSurfaceDelegate` to replace existing logic in `DevSupportManagerBase` to abstract how we show/hide the RedBox surface. The delegate will wrap a RedBoxDialog instance, which is used to show/hide the dialog for default behavior (when there is no surface delegate for redbox got provided).
I also updated the interface for delegate to accomodate new use cases:
- Add `isShowing` for the `SurfaceDelegate`
- Add a list of getters for `DevSupportManager` for data access in the delegate
- (Update 2/7) Separate Dialog from `RedBoxDialog`, and re-named it to `RedBoxContentView`. This is to make it clear that the delegate is responsible to provide actual surface implementation (Dialog). The content view is meant to be shared.
Changelog:
[Android][Internal]
Reviewed By: javache
Differential Revision: D33987835
fbshipit-source-id: 57c20648e7f2ec8238963feca27ccd5518e7931d
Summary:
This diff separates the content view creation logic from existing `RedBoxDialog` logic. After the change, `RedBoxDialog` is no longer a subclass of `Dialog`, but behaves like a dialog with forwarding pattern to delegate dialog API to internal member. This will keep the APIs consistent with dependent components.
The motivation of the change is to make the content view reusable. This is important in VR surface where we don't have activities and necessary implementations for Dialog to show.
Changelog:
[Android][Internal]
Reviewed By: javache
Differential Revision: D34016503
fbshipit-source-id: 261594bda9f6fb2d83764a1e5ec2e9e60d8d39a3
Summary:
We put the `:interfaces` target on the dependencies list for `:devsupport` target in the [BUCK file](https://fburl.com/code/lrr1c0pn). In the following diffs I will need to put the interface [`/devsupport/RedBoxHandler`](https://fburl.com/code/v53euvps) on to [`/devsupport/interfaces/DevSupportManager`](https://fburl.com/code/k8gwxa0f). This violates the dependency rule.
Since `RedBoxHandler` is an interface, I moved it to the interfaces list in this diff to unblock.
Changelog:
[Android][Internal]
Reviewed By: yungsters
Differential Revision: D33987834
fbshipit-source-id: 77a1ee14bd10c6bbaac2ee465ae7050e99ed0399
Summary:
The fix in this diff seems simple, but it took some time to understand why this change fixed the issue that views animated use native driver out from their parent's layout are not getting touch events.
We introduced `overflowInset` to RN Android a while back to give each shadow node extra information to cover all its children's layout. These values (left, top, right, bottom extensions from the view's own layout) help us improve hit-testing algorithm used in touch events. We could ignore all subtrees that the touch point not in their parent's overflowInset box.
However, this was not working for native animation. When `userNativeDriver` is on, all animation happens without Fabric knows anything about them. The overflowInset is out of date with the final animated layout, which caused the issue that we ignored the animated view as we thought it's not under the pointer.
Here is a playground demo (P476407654) for the issue:
https://pxl.cl/1XfPL
We've tried to fix this by passing the final animated values via `passthroughAnimatedPropExplicitValues` added in D32539976. This is a prop that will get merged into `style` prop for [animation component](https://fburl.com/code/jybzfgu5). The transform values were already applied when measuring layout in [Pressability](https://fburl.com/code/5mect2k3), which uses [LayoutableShadowNode](https://fburl.com/code/qh8fufrw). However, this is not the case for overflowInset calculation. Hence, the fix here is to apply the transform matrix in Yoga before calculating the overflowInset.
Changelog:
[Android][Fixed] - Fix overflowInset calculation by using transform values
Reviewed By: ShikaSD
Differential Revision: D33806030
fbshipit-source-id: e438618e3d6e5b0333cff9ff9919b841d73b2e9d
Summary:
The overflowInset uses negative values to indicate extending from parent view. This diff fixes the math so that it's correctly check if the point is within overflowInset.
Changelog
[Android][Fixed] - Fix math for detecting if children views are in parent's overflowInset area.
Reviewed By: genkikondo
Differential Revision: D33750129
fbshipit-source-id: 1a5a33a227280c687b158b4a81a56017b6f4f3e0
Summary:
Per discussion in the previous diff D33672110, it's ok to add the `pointerEvents` prop to scrollview. This will help prevent scrolling on the ScrollView if pointerEvents is set to `box-none`, or `none`.
Corresponding doc changes are in https://github.com/facebook/react-native-website/pull/2936
Changelog:
[Android][Added] - Add new API in ScrollView and HorizontalScrollView to process pointerEvents prop.
Reviewed By: javache
Differential Revision: D33699223
fbshipit-source-id: 1cae5113e9e7d988fc4c4765c41d817a321804c4
Summary:
This diff gates the useage of overflowinset to hit test algorithm to fabric renderer only.
Changelog:
[Internal][Android] - Use overflowInset for fabric only
Reviewed By: JoshuaGross, mdvacca
Differential Revision: D33237281
fbshipit-source-id: e5cd78ee97f62f100d42d016241d1544fb0953ad
Summary:
The previous diff shows how `overflowInset` could improve hit test algorithm performance. This diff adds experiment to it in order to:
1. Understand the perf improvement in production
2. Provide quick way to rollback in production -- the changes are used by FB4A as well as VR
3. The changes will pass more instructions over JNI, which may have impact on perf.
To share the MC param values in both Java and C++ side, the value is hosted by `ReactFeatureFlags` and fetched in `FbReactInstanceHolder`.
Changelog: [Internal]
Reviewed By: mdvacca
Differential Revision: D33179310
fbshipit-source-id: 327100d41f7b5a668ff0d2afabcdd1fc16cb5a18
Summary:
This diff adds `overflowInset` values in RN Android. These values are used to give an enlarged boundary of a view group that also contains all its children layout. Here is [the post](https://fb.workplace.com/groups/yogalayout/permalink/2264980363573947/) that discuss more on why this is useful. I steal the pic in that post here as TLDR:
{F687030994}
In the above case, we will get overflowInset for ViewGroup A as something like `top: 0, right: -20, bottom: -20, left: 0`.
This has been added in the [Fabric core](https://fburl.com/code/f8c5tg7b) and [in IOS](https://fburl.com/code/vkh0hpt6). In Android, since we used to ignore all event coordinates outside of a ViewGroup boundary, this is not an issue. However, that caused unregistered touch area problem and got fixed in D30104853 (https://github.com/facebook/react-native/commit/e35a963bfb93bbbdd92f4dd74d14e2ad6df5e14a), which dropped the boundary check and made the hit test algorithm in [TouchTargetHelper.java](https://fburl.com/code/dj8jiz22) worse as we now need to explore all the child node under ReactRootNode.
This perf issue is getting obvious when a view loads too many items, which matches our experience with "Hover getting slow after scrolling", "Hover getting slow after going back from PDP view", and "The saved list view (in Explore) is very fast (because it has very few components)"
To fix this issue, I added the support to `overflowInset` to RN Android by
1. Sending the `overflowInset` values from Binding.cpp in RN Android as a separate mount instruction
2. Update `IntBufferBatchMountItem.java` to read the int buffer sent over JNI, and pass the `overflowInset` values to `SurfaceMountingManager.java`
3. Creating new interface `ReactOverflowViewWithInset.java` and extending the existing `ReactOverflowView.java` usages
4. Adding implementation of getter and setter for `overflowInset` in various views
5. Update `TouchTargetHelper.java` to read the values and check boundaries before exploring ViewGroup's children
Note that in #3 I didn't change `ReactOverflowView.java` interface directly. I am concerned about backward compatibility issues in case this interface is being used in OSS. I suggest we deprecate it as we are not using it anymore in our code.
Changelog:
[Internal][Android]
Reviewed By: JoshuaGross
Differential Revision: D33133977
fbshipit-source-id: 64e3e837fe7ca6e6dbdbc836ab0615182e10f28c
Summary:
Similar to the previous diff, we should not allow view group that has clipChildren set to true to respond events that are out of bounds.
Changelog:
[Internal][Android]
Reviewed By: ShikaSD
Differential Revision: D33102331
fbshipit-source-id: de3a5ffdd5293ada1d2c211659e79edc697b5d15
Summary:
In D30104853 (https://github.com/facebook/react-native/commit/e35a963bfb93bbbdd92f4dd74d14e2ad6df5e14a), we added fix to the issue where touches on the child view that is outside of its parent view's boundary are not registered. The only exception to that is if the parent view has overflow style `overflow: hidden`. In that case, touches happen outside of the parent view should be ignored.
{F686521911}
That fix works, but it increases the complexity for the DFS algorithm used to find the touch target in two ways:
1. Before we only traverse views that contain the touch event point. If the touch event point is outside of the view, we won't step in and traverse that part of the tree. This is actually what caused the initial problem. The fix removed that boundary check (where `isTransformedTouchPointInView` used to do) and push it later. This increases the number of tree traversal a lot.
2. The check for `overflow: hidden` is happened after we find a potential target view, which means we've spent time to find the target view before we decide if the target view is even a candidate.
This diff aims to update for the #2 item above. Since we are checking the style of the parent view, not the target view, it's not necessary to check that after we find the target view. We could check the parent view and if it has `overflow: hidden` on it, any pointer event that are not in the boundary can be ignored already.
Changelog:
[Internal][Android]
Reviewed By: mdvacca, ShikaSD
Differential Revision: D33079157
fbshipit-source-id: c79c2b38b8affb9ea0fd25b5e880b22466ab7ed9
Summary:
This diff add custom prediction for fling distance support. This is needed for customize fling animator to calculate predicted fling distance, instead of using the overscroller that may not be used by the animator.
More context on this -- when fling happens, our code will first predict the final fling position `p`, apply the snapping logic to decide the expected snapping position `pSnapping` given `p`, scroll velocity and children layout, then trigger the overscroller (existing) or custom fling animator to finish the fling.
Currently, the prediction logic is done with overscroller, and custom fling animator has no control over how the predicted fling distance should be. Changes in this diff allow the animator to override `getExtrapolatedDistance` method and provide that information.
Changelog:
[Android][Added] - Add new API for custom fling animator to provide predicted travel distance for its fling animation.
Reviewed By: mdvacca
Differential Revision: D32571734
fbshipit-source-id: d34b969206f8b6cb5c68d2f50a18749bfebbc97e
Summary:
This diff refactors method `predictFinalScrollPosition` in `ReactScrollView` and `ReactHorizontalScrollView` to the helper class. This will make future changes to the prediction logic easier.
Changelog:
[Internal]
Reviewed By: javache
Differential Revision: D32571735
fbshipit-source-id: 7e7e21ac51f929a017cd43de094ed39478fe4032
Summary:
This diff fixes an edge case where scroll to the end of the list may trigger a bounce back effect.
This issue is a regression from D32487846 (https://github.com/facebook/react-native/commit/f70018b37532622f08f20b2c51cdbfca55d730ea) (See [this comment](https://www.internalfb.com/diff/D32487846 (https://github.com/facebook/react-native/commit/f70018b37532622f08f20b2c51cdbfca55d730ea)?dst_version_fbid=263960175698224&transaction_fbid=566201141113715)) that zero velocity fling at the end of the scroll view makes the next fling animator use previous post animation position. This is due to cached `postAnimationValue` is applied mistakenly.
- Pass velocity instead of velocity sign to the helper class
- Update helper class logic to decide if we need to use post animated value from last fling animation
Changelog:
[Internal]
Reviewed By: javache
Differential Revision: D32566010
fbshipit-source-id: 1c61659030151f8f2c7648ca901b8b4158835538
Summary:
This diff fixes an edge case where fling and snap failed to find the correct target position when children views not fill up all the scrollable space. In this case, the target position would be calculated as the end of the scrollable space, which case the snap logic to go to the end of the scrollable area, instead of stop at the expected snapping position.
Changelog:
[Android][Fixed] - Fix fling and snap with recycler viewgroup where fling to the end of scrollable distance when it goes over current rendered children views.
Reviewed By: mdvacca
Differential Revision: D32565459
fbshipit-source-id: 319ef6e2d4e1c4deb9e45ed02c1bff7d807575c3
Summary:
The helper class for ScrollView should not need to detect the scroll direction. If it has to do so, that means the corresponding logic should live in the `ReactScrollView` or `ReactHorizontalScrollView` respectively.
This diff is to remove the scroll direction detection logic from the scroll view helper. Long term we should keep it this way as the shared code got moved to the helper class from the scroll view classes.
Changelog:
[Internal]
Reviewed By: javache
Differential Revision: D32514429
fbshipit-source-id: 2165f2eba90cc25d14834c39148fe8ce8805bea6
Summary:
This diff fixes two edge case (similar to a race condition) that caused unexpected behaviors.
**Problem one**
{F680816408}
The previous fling animation is not canceled when user starts to scroll or drag. This is causing both the animation and scroll are setting the scroll position. Depends on the animation path and scroll speed, there may be cases where the [velocity calculation](https://fburl.com/code/010lsu72) ends up getting reversed values. See P467905091 as an example where you can see `mXFlingVelocity` goes back and forth from positive to negative.
It's hard to see if the wrong values are in the middle, but if that happens in the end of user gesture, the velocity for the next fling would be wrong. It shows a "bounce back" effect, and can be triggered when user makes small quick joystick scrolls in one direction.
**Problem two**
{F680821494}
There is a gap between animator's `onAnimationEnd` lifecycle method [finished](https://fburl.com/code/6baq04ne) and the `Animator#isRunning` API to return false. This is causing issues for `getPostAnimationScrollX` where we [decide to return](https://fburl.com/code/hzzugvch) the animated final value or the scroll value. User may see the `-1` value got used for the next fling start value, and the whole scroll view goes back to the beginning of scroll view and starts to fling.
This happens when the previous fling animation finishes and the animated final value is set to -1, but at the same time the next fling starts before `isRunning` returns false for the previous animation.
**Solution**
The problems are fixed by
- Do not reset animated final value to -1 in `onAnimationEnd` method
- Add `mIsFinished` states and use it to track animation finish signal, instead of using `isRunning` API
- Update logic where we decide to return the correct value for the next animation starts point. We will return previous animated final value when the animation got canceled, and user is going towards that value from the current scroll value.
Changelog:
[Android][Fixed] - Fixed edge case for quick small scrolls causing unexpected scrolling behaviors.
Reviewed By: javache
Differential Revision: D32487846
fbshipit-source-id: f1b0647656e021390e3a05de5846251a4a2647ff
Summary:
This diff makes the fling animator cuztomizable, so that the subclasses can have their own animation for fling behavior.
Before the diff, we rely on the `OverScroller` to `fling`, which has some issues with Spline interpolation being messed up due to the clamped fling distance (See more details in T105464095). This may not be a big issue for mobile when user touches screen, but in VR environment this shows up very clearly with joystick events. To fix that properly without affecting mobile behavior, I added a new interface `HasFlingAnimator` from the helper, and implemented with default fling animator in the OSS ScrollView.
We should consider adopt a suitable animator for mobile platform, as the non-smooth fling effect is also happening in mobile.
- Add interface `HasFlingAnimator` to `ReactScrollView` and `ReactHorizontalScrollView`
- Add default fling animator
- Depend on if the default animator is used, customize the flingAndSnap behavior
Changelog:
[Internal]
Reviewed By: JoshuaGross
Differential Revision: D32382806
fbshipit-source-id: 08f03350f6a9b9fc03414b4dcb9977b9f33603ba
Summary:
This diff refactors the scroll animation from `ReactScrollView` and `ReactHorizontalScrollView` into the `ReactScrollViewHelper` to reduce repeated code. The `Animator` is now shared between all the scroll views in the app, which I believe is the right behavior.
It also helps to make the animator changes in future diffs apply to both horizontal and vertical scroll view.
- Move `reactSmoothScrollTo` to `smoothScrollTo` in the helper class
- This means one Animator for all ScrollViews
- Move `updateStateOnScroll` to the helper class
- Add interface for accessing instance scroll state properties in ScrollView
- This means each ScrollView keeps their own scrolling state
- Use `Point` class for pairs of x and y values
Changelog:
[Internal]
Reviewed By: javache
Differential Revision: D32372180
fbshipit-source-id: 529180eea788863689c3b440191ed50c5a6f04e5
Summary:
Changelog:
[Android][Added] Adding new API `onChildEndedNativeGesture` to the RootView interface to let its implementations notify the JS side that a child gesture is ended.
Reviewed By: javache
Differential Revision: D32228745
fbshipit-source-id: ad1f26546dd60f9c5a569b0bc3ad5020a01b90cc
Summary:
When calculating the offset range, we assume the first item is always at offset zero position and skipped that (as the smallerOffset is zero). However, this may not be the case in some situations. This diff changes the range measuring loop to always start from the first item.
Changelog:
[Android][Fixed] - Do NOT skip the first child view in the scroll view group when measuring the lower and upper bounds for snapping.
Reviewed By: mdvacca
Differential Revision: D31887086
fbshipit-source-id: af7221a621b2719d057afa6b64aa91c94ac01295
Summary:
The `ReactScrollView.java` constructor is using `ReactContext` instead of `Context`, which is inconsistent to the horizontal scroll view. This is the result from D3863966 (https://github.com/facebook/react-native/commit/2cf2fdbc04bc5309f6942ed464ad61cd06a26ce8) when an OSS issue needs to be addressed. That issue and all call sites to use the `ReactContext` are deprecated now.
Revert this back to use `Context` to be less restrictive.
Changelog:
[Android][Fixed] - Revert `ReactScrollView` to use `Context` instead of `ReactContext` in the constructor to be less restrictive.
Reviewed By: javache
Differential Revision: D31819799
fbshipit-source-id: 3f00d64850aebd2e20615033b2e1f1c721fed37e
Summary:
This issue is found when investigating T101563978 with IOS platform. When animation is off, the x position measurement is off after `scrollToItem` is called.
The android fix is checked in at D31492685 (https://github.com/facebook/react-native/commit/1a9e2d5d5589ce5cee92868ea5bccceb6e161eff). For IOS, the correct state data is updated only for animated cases, but not for instant scroll cases. This diff unified them.
Changelog
[IOS][Fixed] Fixed an edge case when scroll to item/index is called without animation, the offset position is not updated. This caused the measurement of the position to be wrong.
Reviewed By: sammy-SC
Differential Revision: D31564169
fbshipit-source-id: 89f47d8054afb03c2ace1d595163b160e5bb2036
Summary:
The `scrollTo` method in ScrollViews are using the `(x, y)` position they got from upperstream to scroll, and to set the state for Fabric. This diff fixes an edge case where the scroll result is not ended up to `(x, y)`. For example, if we are going to scroll to the last item in the list, the item may not scroll to the `(x, y)` position, but stay at the end position of the view.
- Change `scrollTo` method to use the actual `scrollX` and `scrollY` position after scrolling to set current state.
Changelog:
[Android][Fixed] - scrollTo API in ScrollView will check the actual scroll position before setting the scroll state
Reviewed By: JoshuaGross
Differential Revision: D31492685
fbshipit-source-id: e5513fb735ea68c5014b5c47fadffe461cad5c94
Summary:
When the overflow style set to 'scroll', React ViewGroup does nothing to the container. Instead it should be clipped just like hidden.
Changelog:
[Android][Changed] - Setting `overflow: scroll` in View component style will clip the children in the View container
Reviewed By: javache
Differential Revision: D31350605
fbshipit-source-id: e0d618f5e872fec9cf9ecb2d4cfe7af9a2f3c063
Summary:
This diff introduces a new interface named `SurfaceDelegate`. The interface abstracts the API for interacting with a surface, which is required for platforms other than mobile to implement how it wants to show and hide a surface. For existing Mobile use cases, the `LogBoxDialogSurfaceDelegate` is provided as a fallback solution so everything still works.
Changelog:
[Android][Added] - Add SurfaceDelegate abstraction to support interaction in multiple platforms and provide default implementation in LogBoxModule
Reviewed By: mdvacca
Differential Revision: D31132285
fbshipit-source-id: 13315a8bc5b7bcaee9b5e53ef5c6f6cc8cb01f31