Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 82 additions & 65 deletions ios/RNCPagerViewComponentView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -176,24 +176,9 @@ - (void)updateProps:(const facebook::react::Props::Shared &)props oldProps:(cons
[super updateProps:props oldProps:oldProps];
}

- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
RCTRNCViewPagerHandleCommand(self, commandName, args);
}

#pragma mark - Internal methods

- (void)setPage:(NSInteger)index {
[self goTo:index animated:YES];
}

- (void)setPageWithoutAnimation:(NSInteger)index {
[self goTo:index animated:NO];
}

- (void)setScrollEnabledImperatively:(BOOL)scrollEnabled {
[scrollView setScrollEnabled:scrollEnabled];
}

- (void)disableSwipe {
self.nativePageViewController.view.userInteractionEnabled = NO;
}
Expand Down Expand Up @@ -244,9 +229,9 @@ - (void)setPagerViewControllers:(NSInteger)index
__strong RNCPagerViewComponentView *strongSelf = weakSelf;
[strongSelf enableSwipe];
if (strongSelf->_eventEmitter != nullptr ) {
const auto strongEventEmitter = *std::dynamic_pointer_cast<const RNCViewPagerEventEmitter>(strongSelf->_eventEmitter);
const auto eventEmitter = [strongSelf pagerEventEmitter];
int position = (int) index;
strongEventEmitter.onPageSelected(RNCViewPagerEventEmitter::OnPageSelected{.position = static_cast<double>(position)});
eventEmitter->onPageSelected(RNCViewPagerEventEmitter::OnPageSelected{.position = static_cast<double>(position)});
strongSelf->_currentIndex = index;
}
[strongSelf updateLayoutMetrics:strongSelf->_layoutMetrics oldLayoutMetrics:strongSelf->_oldLayoutMetrics];
Expand Down Expand Up @@ -279,14 +264,14 @@ - (UIViewController *)currentlyDisplayed {
#pragma mark - UIScrollViewDelegate

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
const auto strongEventEmitter = *std::dynamic_pointer_cast<const RNCViewPagerEventEmitter>(_eventEmitter);
strongEventEmitter.onPageScrollStateChanged(RNCViewPagerEventEmitter::OnPageScrollStateChanged{.pageScrollState = RNCViewPagerEventEmitter::OnPageScrollStateChangedPageScrollState::Dragging });
const auto eventEmitter = [self pagerEventEmitter];
eventEmitter->onPageScrollStateChanged(RNCViewPagerEventEmitter::OnPageScrollStateChanged{.pageScrollState = RNCViewPagerEventEmitter::OnPageScrollStateChangedPageScrollState::Dragging });
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {

const auto strongEventEmitter = *std::dynamic_pointer_cast<const RNCViewPagerEventEmitter>(_eventEmitter);
strongEventEmitter.onPageScrollStateChanged(RNCViewPagerEventEmitter::OnPageScrollStateChanged{.pageScrollState = RNCViewPagerEventEmitter::OnPageScrollStateChangedPageScrollState::Settling });
const auto eventEmitter = [self pagerEventEmitter];
eventEmitter->onPageScrollStateChanged(RNCViewPagerEventEmitter::OnPageScrollStateChanged{.pageScrollState = RNCViewPagerEventEmitter::OnPageScrollStateChangedPageScrollState::Settling });

if (!_overdrag) {
NSInteger maxIndex = _nativeChildrenViewControllers.count - 1;
Expand All @@ -299,44 +284,26 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoi
CGPoint croppedOffset = [self isHorizontal] ? CGPointMake(topBound, 0) : CGPointMake(0, topBound);
*targetContentOffset = croppedOffset;

strongEventEmitter.onPageScrollStateChanged(RNCViewPagerEventEmitter::OnPageScrollStateChanged{.pageScrollState = RNCViewPagerEventEmitter::OnPageScrollStateChangedPageScrollState::Idle });
eventEmitter->onPageScrollStateChanged(RNCViewPagerEventEmitter::OnPageScrollStateChanged{.pageScrollState = RNCViewPagerEventEmitter::OnPageScrollStateChangedPageScrollState::Idle });
}
}


}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
const auto strongEventEmitter = *std::dynamic_pointer_cast<const RNCViewPagerEventEmitter>(_eventEmitter);
strongEventEmitter.onPageScrollStateChanged(RNCViewPagerEventEmitter::OnPageScrollStateChanged{.pageScrollState = RNCViewPagerEventEmitter::OnPageScrollStateChangedPageScrollState::Idle });
}

- (BOOL)isHorizontalRtlLayout {
return self.isHorizontal && !self.isLtrLayout;
}

- (BOOL)isHorizontal {
return _nativePageViewController.navigationOrientation == UIPageViewControllerNavigationOrientationHorizontal;
const auto eventEmitter = [self pagerEventEmitter];
eventEmitter->onPageScrollStateChanged(RNCViewPagerEventEmitter::OnPageScrollStateChanged{.pageScrollState = RNCViewPagerEventEmitter::OnPageScrollStateChangedPageScrollState::Idle });
}

- (BOOL)isLtrLayout {
return [_layoutDirection isEqualToString: @"ltr"];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint point = scrollView.contentOffset;

float offset = 0;

if (self.isHorizontal) {
if (scrollView.frame.size.width != 0) {
offset = (point.x - scrollView.frame.size.width)/scrollView.frame.size.width;
}
} else {
if (scrollView.frame.size.height != 0) {
offset = (point.y - scrollView.frame.size.height)/scrollView.frame.size.height;
}
CGFloat contentOffset = [self isHorizontal] ? scrollView.contentOffset.x : scrollView.contentOffset.y;
CGFloat frameSize = [self isHorizontal] ? scrollView.frame.size.width : scrollView.frame.size.height;

if (frameSize == 0) {
return;
}

float offset = (contentOffset - frameSize)/frameSize;

float absoluteOffset = fabs(offset);

Expand Down Expand Up @@ -372,21 +339,10 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
}

float interpolatedOffset = absoluteOffset * labs(_destinationIndex - _currentIndex);

const auto strongEventEmitter = *std::dynamic_pointer_cast<const RNCViewPagerEventEmitter>(_eventEmitter);
int eventPosition = (int) position;
strongEventEmitter.onPageScroll(RNCViewPagerEventEmitter::OnPageScroll{.position = static_cast<double>(eventPosition), .offset = interpolatedOffset});

// This is temporary workaround to allow animations based on onPageScroll event
// until Fabric implements proper NativeAnimationDriver,
// see: https://github.com/facebook/react-native/blob/44f431b471c243c92284aa042d3807ba4d04af65/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm#L59
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[[RCTOnPageScrollEvent alloc] initWithReactTag:[NSNumber numberWithInt:self.tag] position:@(position) offset:@(interpolatedOffset)], @"event", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"RCTNotifyEventDispatcherObserversOfEvent_DEPRECATED"
object:nil
userInfo:userInfo];

[self sendScrollEventsForPosition:position offset:interpolatedOffset];
}


#pragma mark - UIPageViewControllerDelegate

- (void)pageViewController:(UIPageViewController *)pageViewController
Expand All @@ -398,9 +354,9 @@ - (void)pageViewController:(UIPageViewController *)pageViewController
NSUInteger currentIndex = [_nativeChildrenViewControllers indexOfObject:currentVC];
_currentIndex = currentIndex;
int position = (int) currentIndex;
const auto strongEventEmitter = *std::dynamic_pointer_cast<const RNCViewPagerEventEmitter>(_eventEmitter);
strongEventEmitter.onPageSelected(RNCViewPagerEventEmitter::OnPageSelected{.position = static_cast<double>(position)});
strongEventEmitter.onPageScroll(RNCViewPagerEventEmitter::OnPageScroll{.position = static_cast<double>(position), .offset = 0.0});
const auto eventEmitter = [self pagerEventEmitter];
eventEmitter->onPageSelected(RNCViewPagerEventEmitter::OnPageSelected{.position = static_cast<double>(position)});
eventEmitter->onPageScroll(RNCViewPagerEventEmitter::OnPageScroll{.position = static_cast<double>(position), .offset = 0.0});
}
}

Expand All @@ -419,6 +375,67 @@ - (UIViewController *)pageViewController:(UIPageViewController *)pageViewControl
return [self nextControllerForController:viewController inDirection:direction];
}

#pragma mark - Imperative methods exposed to React Native

- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
RCTRNCViewPagerHandleCommand(self, commandName, args);
}

- (void)setPage:(NSInteger)index {
[self goTo:index animated:YES];
}

- (void)setPageWithoutAnimation:(NSInteger)index {
[self goTo:index animated:NO];
}

- (void)setScrollEnabledImperatively:(BOOL)scrollEnabled {
[scrollView setScrollEnabled:scrollEnabled];
}

#pragma mark - Helpers

- (BOOL)isHorizontalRtlLayout {
return self.isHorizontal && !self.isLtrLayout;
}

- (BOOL)isHorizontal {
return _nativePageViewController.navigationOrientation == UIPageViewControllerNavigationOrientationHorizontal;
}

- (BOOL)isLtrLayout {
return [_layoutDirection isEqualToString: @"ltr"];
}

- (std::shared_ptr<const RNCViewPagerEventEmitter>)pagerEventEmitter
{
if (!_eventEmitter) {
return nullptr;
}

assert(std::dynamic_pointer_cast<const RNCViewPagerEventEmitter>(_eventEmitter));
return std::static_pointer_cast<const RNCViewPagerEventEmitter>(_eventEmitter);
}

- (void)sendScrollEventsForPosition:(NSInteger)position offset:(CGFloat)offset {
const auto eventEmitter = [self pagerEventEmitter];
eventEmitter->onPageScroll(RNCViewPagerEventEmitter::OnPageScroll{
.position = static_cast<double>(position),
.offset = offset
});

// This is temporary workaround to allow animations based on onPageScroll event
// until Fabric implements proper NativeAnimationDriver,
// see: https://github.com/facebook/react-native/blob/44f431b471c243c92284aa042d3807ba4d04af65/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm#L59
RCTOnPageScrollEvent *event = [[RCTOnPageScrollEvent alloc] initWithReactTag:@(self.tag)
position:@(position)
offset:@(offset)];
NSDictionary *userInfo = @{@"event": event};
[[NSNotificationCenter defaultCenter] postNotificationName:@"RCTNotifyEventDispatcherObserversOfEvent_DEPRECATED"
object:nil
userInfo:userInfo];
}

#pragma mark - RCTComponentViewProtocol

+ (ComponentDescriptorProvider)componentDescriptorProvider
Expand Down
Loading