Summary:In order to ensure that the docked sticky header in a ListView receives touches correctly, RCTScrollView has a custom hitTest implementation that checks the sticky headers for touches prior to checking any other views.
There was a bug in this implementation that meant that sticky views would get touch priority even if the touch was outside the bounds of the scrollView. This meant that sticky headers that scrolled off the top of the list would intercept touches intended for views placed above the scrollView.
This diff fixes that bug by checking that the touch is inside the scrollview before checking for sticky header touches. I've also limited the custom hit test logic to just the currently docked header, as the other sticky header views do not require special treatment.
Reviewed By: javache
Differential Revision: D3041236
fb-gh-sync-id: a2a3474dda03d5b51688bd575195a67956184bbe
shipit-source-id: a2a3474dda03d5b51688bd575195a67956184bbe
Summary:Currently, an empty `<ScrollView />` on iOS always throws the warning "Sticky header index 0 was outside the range {0, 0}".
This is because the error-reporting code relies on the assumption that `stickyHeaderIndices` exists, and when it doesn't the error check thinks there's an index when there really isn't.
Note that this only changes error reporting and won't affect apps out of debug mode.
**Test plan**
I created a sample app and included an empty `<ScrollView />`. Without this change the "Sticky header..." warning was displayed on every run through. With this change implemented, the warning went away.
Closes https://github.com/facebook/react-native/pull/6417
Differential Revision: D3042178
Pulled By: nicklockwood
fb-gh-sync-id: 7afefd428a5fcb03867bcb69e46c46fe1ae9151e
shipit-source-id: 7afefd428a5fcb03867bcb69e46c46fe1ae9151e
Summary:When a component prop is set to null/undefined, and doesn't have a default value specified in `getDefaultProps`, the null value is sent over the bridge as a sentinel to reset to the original native value.
On iOS this is handled by creating a default view instance for each view type. The default view is then used to look up the unmodified value for any prop that is reset.
This is rather expensive however, as it means that for complex views (e.g. WebView, MapView), a minimum of two instances will be created even if only one is needed, and the default view will remain even after all actual view instances have been released.
This diff replaces the default view mechanism with a system where the default value of each prop is recorded the first time it is set. This avoids the need to keep an extra copy of the whole view.
The only exception is for props that use the `RCT_CUSTOM_VIEW_PROPERTY` macro, which includes the default view as part of the interface. To avoid a breaking change, a default view will still be created for views that use this macro, but only if they are sent a null value (so very rarely, in practice). In a future update we may deprecate or replace `RCT_CUSTOM_VIEW_PROPERTY` if there are significant benefits to doing so.
Reviewed By: javache
Differential Revision: D3012115
fb-gh-sync-id: 259348e54aa8342f444ad182b6f883d2dd684973
shipit-source-id: 259348e54aa8342f444ad182b6f883d2dd684973
Summary:Fixes the RefreshControl layout after a screen rotation. See #6311 for a more detailed explanation. I fixed it by adjusting the frame of the RefreshControl in `layoutSubviews` of the parent ScrollView.
While working on fixing this I noticed that when doing a 'pull to refresh' and then not scrolling and wait for it to end the next one will not behave like the first one (it will require pulling further down for the spinner to start spinning). I fixed that too by scrolling the scrollview back to 0 manually before calling `UIRefreshControl.endRefreshing`.
**Test plan (required)**
Tested using the UIExplorer RefreshControl example.
When doing a pull to refresh and then rotating the screen the RefreshControl must stay positioned properly.
Doing multiple consecutive pull to refresh without scrolling after should all behave the same.
Fixes#6311
Closes https://github.com/facebook/react-native/pull/6359
Differential Revision: D3023727
fb-gh-sync-id: f50ae52ea769c2b3e5025c362544a8809a71aa00
shipit-source-id: f50ae52ea769c2b3e5025c362544a8809a71aa00
Summary:The bug is caused by a weird race condition. What happens is that when calling `UIRefreshControl#endRefreshing` the `UIScrollView` delegate `scrollViewDidScroll` function is called synchronously and then `dockClosestSectionHeader` crashes because the sticky header indexes are updated but not the contentView children.
I fixed it by adding an updating property on `RCTRefreshControl` and setting it before calling `endRefreshing` so we can know not to call `dockClosestSectionHeader` at that moment.
Tested with both `RefreshControl` and `onRefreshStart` prop.
I reproduced the bug by replacing ListViewExample.js in UIExplorer with https://gist.github.com/janicduplessis/05fc58e852f3e80e51b9Fixes#5440
cc nicklockwood
Closes https://github.com/facebook/react-native/pull/5445
Differential Revision: D2953984
Pulled By: nicklockwood
fb-gh-sync-id: c17a6a75ab31ef54d478706ed17a8115a11d734e
shipit-source-id: c17a6a75ab31ef54d478706ed17a8115a11d734e
Summary:
When scrolling while RefreshControl is refreshing the sticky headers are offset by the height of the UIRefreshControl. This simply removes the height of the UIRefreshControl while it is refreshing and fixes the problem.
You can repro the bug using this example in UIExplorer by doing a pull to refresh and scrolling the ListView immediately after.
https://gist.github.com/janicduplessis/26b4f2758e90b2aa1620Fixes#5405
Closes https://github.com/facebook/react-native/pull/5517
Reviewed By: svcscm
Differential Revision: D2895623
Pulled By: nicklockwood
fb-gh-sync-id: 81df36cccfc3e7b973c2be78565f8b8408c9fc12
Summary:
I want to use the `RCTEvent` protocol for touch events as well. That's why I'm removing not very well defined `body` property and replacing it with `arguments` method, which will return an array that will be passed directly to the js call.
I think this makes sense because there is no unified arguments format for all events and and the called js method (`moduleDotMethod`) is already event specific.
This way touch events and scroll events can result in calling a completely different js function with a completely different arguments (what they indeed currently do).
public
___
//This diff is part of a larger stack. For high level overview what's going on jump to D2884593.//
Reviewed By: nicklockwood
Differential Revision: D2884590
fb-gh-sync-id: 2c1885c3414e255d8572c0fbbbfe62a23d94dd06
Summary:
This property was never used, so I'm removing it.
public
___
//This diff is part of a larger stack. For high level overview what's going on jump to D2884593.//
Reviewed By: javache
Differential Revision: D2884587
fb-gh-sync-id: acd5e576cd13a02e77225f3b308232f8331d3b61
Summary:
Both iOS and Android currently support some sort of native pull to refresh control but the API was very different. I tried implementing a component based on PullToRefreshViewAndroid but that works on both platforms.
I liked the idea of wrapping the ListView or ScrollView with the PullToRefreshView component and allow styling the refresh view with platform specific props if needed. I also like the fact that 'refreshing' is a controlled prop so there is no need to keep a ref to the component or to the stopRefreshing function.
It is a pretty rough start so I'm looking for feedback and ideas to improve on the API before cleaning up everything.
On iOS we could probably deprecate the onRefreshStart property of the ScrollView and implement the native stuff in a PullToRefreshViewManager. We could then add props to customize the look of the UIRefreshControl (tintColor). We could also deprecate the Android only component and remove it later.
Closes https://github.com/facebook/react-native/pull/4915
Reviewed By: svcscm
Differential Revision: D2799246
Pulled By: nicklockwood
fb-gh-sync-id: 75872c12143ddbc05cc91900ab4612e477ca5765
Summary:
When we nest scrollviews, the hack in handleCustomPan: will cause the scroll to stall and break.
There's still some weird behaviour inside ScrollResponder.js but this does not seem the affect the scrollview's scrolling.
public
Reviewed By: fionaf, jingc, majak
Differential Revision: D2713639
fb-gh-sync-id: ad898ead62415bc14c91bc84fdfdb8c0fbb32b06
Summary: public
Added lightweight genarics annotations to make the code more readable and help the compiler catch bugs.
Fixed some type bugs and improved bridge validation in a few places.
Reviewed By: javache
Differential Revision: D2600189
fb-gh-sync-id: f81e22f2cdc107bf8d0b15deec6d5b83aacc5b56
Summary:
This diff removes calls to `-updateClippedSubviews` by only re-clipping when the scroll view moves by a certain number of pixels.
leeway = 50pt => 46.9% of calls removed
leeway = 10pt => 13.2% " " "
Summary:
Our events all follow a common pattern, so there's no good reason why the configuration should be so verbose. This diff eliminates that redundancy, and gives us the freedom to simplify the underlying mechanism in future without further churning the call sites.
Summary: At the moment the `ListView.js` `_childFrames` variable is only updated on scroll. As a consequence, `onChangeVisibleRows` won't get triggered for the initial render, nor any future render not trigered by scroll events. To fix this we need to make sure native and JS have the child frames in sync.
Summary:
The `ScrollView` sends important `updatedChildFrames` data to the `ListView` to be able to implement `onChangeVisibleRows` method. Coalescing operates very strongly on older devices like the iPhone 4s where this data is then lost.
Fixes#1782.
`ListView` has a method called `onChangeVisibleRows` that is called whenever the rows visible on screen change. This method is critical to be able to implement deletion/creation of views and hence be conservative in memory usage. I have an infinite scrolling view which uses this method to only render the full rows for what is visible on screen and put placeholders for everything else.
In the `RCTEventDispatcher`, we [coalesce events](522fd33d6f/React/Base/RCTEventDispatcher.m (L135-L152)) that are meant to be sent across the bridge. They are [dequeued](522fd33d6f/React/Base/RCTEventDispatcher.m (L180-L188)) on each
Closes https://github.com/facebook/react-native/pull/1783
Github Author: Param Aggarwal <paramaggarwal@gmail.com>
Summary:
In some case, it is very useful to have `velocity` and `targetContentOffset` parameters for `ScrollEndDrag` event. I just added them.
Closes https://github.com/facebook/react-native/pull/1500
Github Author: =?UTF-8?q?=E6=AD=A3=E9=9C=96?= <zhenglin.lzl@alibaba-inc.com>
Test Plan: Imported from GitHub, without a `Test Plan:` line.
Summary:
@public
I've increased the warning levels in the OSS frameworks, which caught a bunch of minor issues. I also fixed some new errors in Xcode 7 relating to designated initializers and TLS security.
Test Plan:
* Test the sample apps and make sure they still work.
* Run tests.
Summary:
As per discussion with @nicklockwood in #875, make `RCTScrollView` check its sticky headers for hitTests first.
Closes https://github.com/facebook/react-native/pull/1415
Github Author: Brent Vatne <brent.vatne@madriska.com>
Test Plan:
Have a sticky header in a ScrollView with a Touchable onPress action, scroll a bit after it docks and try tapping, should respond to tap.
Summary:
We need to unset `clipsToBounds` on both the wrapper and the inner custom
scroll view
@public
Test Plan:
`overflow: 'visible'` actually shows content outside the `ScrollView`
(e.g. for full-bleed horizontal scrollers/carousels). It doesn't pick up
touches though, which is a wider issue.