callstack / callstack/react-native-pager-view

Incorrect page change detected when scrolling outside of view

Open
#590 1 comment 3 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
3.4k
Forks
476
Avg merge
10d 21h
Merged PRs (30d)
2

Description

## Environment
package | version
-- | --
react-native-tab-view | 3.1.1
react-native-pager-view | 5.4.9
react-native | 0.64.3
expo | 44.0.0
node | 12.13.0
npm or yarn | yarn@v1.22.18

## Description

Using [react-native-tab-view](https://github.com/satya164/react-native-tab-view), we have a `TabView` and a sidebar to the side of it. When you swipe on the `TabView` and drag it over the sidebar it registers a page switch but it doesn't handle it properly so no page selected event is emitted. The code around this is based in `react-native-pager-view`.

Also reported in that repo, https://github.com/satya164/react-native-tab-view/issues/1365.

### Current behavior

I have a `TabView` alongside a sidebar. When a swipe is started on the view and is released at edge of the sidebar, the tab index doesn't change (`onIndexChange()` isn't called) but the tab still changes. This leaves the tabs in an incorrect state and some of the tabs can't be switched to.

https://user-images.githubusercontent.com/84314259/175305002-1deba6e6-e71e-43ac-ad46-c3b11382364a.mp4

### Expected behavior

When a full swipe happens then the tab is changed correctly. Perhaps once the swipe leaves the view then it counts it as swiped, rather than waiting until the swipe is released.

## Reproducible Demo
I've forked the `react-native-tab-view` repo and added the sidebar to the example code.

[aaulthudl/react-native-tab-view](https://github.com/aaulthudl/react-native-tab-view)

## Patch Fix
We've added a patch using `patch-package` to automatically switch pages properly when the swipe leaves the container. It doesn't have a bounce animation when switching pages though.

```patch
diff --git a/node_modules/react-native-pager-view/.DS_Store b/node_modules/react-native-pager-view/.DS_Store
new file mode 100644
index 0000000..7083c2c
Binary files /dev/null and b/node_modules/react-native-pager-view/.DS_Store differ
diff --git a/node_modules/react-native-pager-view/ios/.DS_Store b/node_modules/react-native-pager-view/ios/.DS_Store
new file mode 100644
index 0000000..40daf43
Binary files /dev/null and b/node_modules/react-native-pager-view/ios/.DS_Store differ
diff --git a/node_modules/react-native-pager-view/ios/ReactNativePageView.m b/node_modules/react-native-pager-view/ios/ReactNativePageView.m
index 9f8ed5b..8ddad58 100644
--- a/node_modules/react-native-pager-view/ios/ReactNativePageView.m
+++ b/node_modules/react-native-pager-view/ios/ReactNativePageView.m
@@ -476,6 +476,16 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat contentOffset =[self isHorizontal] ? scrollView.contentOffset.x : scrollView.contentOffset.y;
CGFloat topBound = [self isHorizontal] ? scrollView.bounds.size.width : scrollView.bounds.size.height;

+ // If a drag goes outside of the content container it should end the drag
+ CGFloat lastContentOffset = [self isHorizontal] ? self.lastContentOffset.x : self.lastContentOffset.y;
+ if (contentOffset <= 0 && lastContentOffset != 0) {
+ scrollView.scrollEnabled = NO;
+ scrollView.scrollEnabled = YES;
+
+ [self goTo:position animated:YES];
+ return;
+ }
+
if ((isFirstPage && contentOffset <= topBound) || (isLastPage && contentOffset >= topBound)) {
CGPoint croppedOffset = [self isHorizontal] ? CGPointMake(topBound, 0) : CGPointMake(0, topBound);
scrollView.contentOffset = croppedOffset;
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.