Skip to content
Merged
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ PODS:
- React-jsinspector (0.70.5)
- React-logger (0.70.5):
- glog
- react-native-pager-view (6.1.1):
- react-native-pager-view (6.1.2):
- React-Core
- react-native-safe-area-context (3.4.1):
- React-Core
Expand Down Expand Up @@ -617,7 +617,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: 31564fa6912459921568e8b0e49024285a4d584b
React-jsinspector: badd81696361249893a80477983e697aab3c1a34
React-logger: fdda34dd285bdb0232e059b19d9606fa0ec3bb9c
react-native-pager-view: 3c66c4e2f3ab423643d07b2c7041f8ac48395f72
react-native-pager-view: 54bed894cecebe28cede54c01038d9d1e122de43
react-native-safe-area-context: 9e40fb181dac02619414ba1294d6c2a807056ab9
React-perflogger: e68d3795cf5d247a0379735cbac7309adf2fb931
React-RCTActionSheet: 05452c3b281edb27850253db13ecd4c5a65bc247
Expand Down
12 changes: 3 additions & 9 deletions ios/ReactNativePageView.h → ios/RNCPagerView.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,17 @@

NS_ASSUME_NONNULL_BEGIN

@interface ReactNativePageView: UIView
@interface RNCPagerView: UIView

- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol> )eventDispatcher;

@property(nonatomic) NSInteger initialPage;
@property(nonatomic) NSInteger lastReportedIndex;
@property(nonatomic) NSInteger destinationIndex;
@property(nonatomic) NSInteger currentIndex;
@property(nonatomic) NSInteger pageMargin;
@property(nonatomic, readonly) BOOL scrollEnabled;
@property(nonatomic) NSString* orientation;
@property(nonatomic, readonly) UIScrollViewKeyboardDismissMode dismissKeyboard;
@property(nonatomic) UIPageViewControllerNavigationOrientation orientation;
@property(nonatomic, copy) RCTDirectEventBlock onPageSelected;
@property(nonatomic, copy) RCTDirectEventBlock onPageScroll;
@property(nonatomic, copy) RCTDirectEventBlock onPageScrollStateChanged;
@property(nonatomic) BOOL overdrag;
@property(nonatomic) NSString* layoutDirection;
@property(nonatomic, assign) BOOL animating;

- (void)goTo:(NSInteger)index animated:(BOOL)animated;
Expand Down
188 changes: 188 additions & 0 deletions ios/RNCPagerView.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@

#import "RNCPagerView.h"
#import "React/RCTLog.h"
#import <React/RCTViewManager.h>

#import "UIViewController+CreateExtension.h"
#import "RCTOnPageScrollEvent.h"
#import "RCTOnPageScrollStateChanged.h"
#import "React/RCTUIManagerObserverCoordinator.h"
#import "RCTOnPageSelected.h"
#import <math.h>

@interface RNCPagerView () <UIScrollViewDelegate>

@property(nonatomic, strong) id<RCTEventDispatcherProtocol> eventDispatcher;

@property(nonatomic, strong) UIScrollView *scrollView;
@property(nonatomic, strong) UIView *containerView;

- (void)goTo:(NSInteger)index animated:(BOOL)animated;
- (void)shouldScroll:(BOOL)scrollEnabled;
- (void)shouldDismissKeyboard:(NSString *)dismissKeyboard;

@end

@implementation RNCPagerView {
uint16_t _coalescingKey;
}

- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher {
if (self = [super init]) {
_initialPage = 0;
_dismissKeyboard = UIScrollViewKeyboardDismissModeNone;
_coalescingKey = 0;
_eventDispatcher = eventDispatcher;
_orientation = @"horizontal";
[self embed];
}
return self;
}

- (void)layoutSubviews {
[super layoutSubviews];
[self calculateContentSize];
}

- (void)didUpdateReactSubviews {
[self calculateContentSize];
}

-(void) insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex {
[super insertReactSubview:subview atIndex:atIndex];
[_containerView insertSubview:subview atIndex:atIndex];
}

- (void)removeReactSubview:(UIView *)subview {
[super removeReactSubview:subview];
[subview removeFromSuperview];

if ([self getCurrentPage] >= self.reactSubviews.count - 1) {
[self goTo:self.reactSubviews.count - 1 animated:false];
}
}

- (void)embed {
_scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_scrollView.delaysContentTouches = NO;
_scrollView.delegate = self;
_scrollView.pagingEnabled = YES;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
[self addSubview:_scrollView];

_containerView = [[UIView alloc] initWithFrame:self.bounds];
[_scrollView addSubview:_containerView];
}

- (void)didSetProps:(NSArray<NSString *> *)changedProps {
if ([changedProps containsObject:@"overdrag"]) {
[_scrollView setBounces:_overdrag];
}
}

- (void)shouldScroll:(BOOL)scrollEnabled {
if (self.scrollView) {
self.scrollView.scrollEnabled = scrollEnabled;
}
}

- (void)shouldDismissKeyboard:(NSString *)dismissKeyboard {
_dismissKeyboard = [dismissKeyboard isEqual: @"on-drag"] ?
UIScrollViewKeyboardDismissModeOnDrag : UIScrollViewKeyboardDismissModeNone;
self.scrollView.keyboardDismissMode = _dismissKeyboard;
}

#pragma mark - Internal methods

- (void) calculateContentSize {
UIView *initialView = self.containerView.subviews.firstObject;
if (!initialView) {
return;
}

CGFloat totalSubviewsWidth = initialView.frame.size.width * self.containerView.subviews.count;
CGFloat totalSubviewsHeight = initialView.frame.size.height * self.containerView.subviews.count;


if ([self isHorizontal]) {
_scrollView.contentSize = CGSizeMake(totalSubviewsWidth, 0);
_containerView.frame = CGRectMake(0, 0, totalSubviewsWidth, initialView.bounds.size.height);
} else {
_scrollView.contentSize = CGSizeMake(0, totalSubviewsHeight);
_containerView.frame = CGRectMake(0, 0, initialView.bounds.size.width, totalSubviewsHeight);
}

_scrollView.frame = self.bounds;
[self.scrollView layoutIfNeeded];

if (self.initialPage != 0) {
[self goTo:self.initialPage animated:false];
}
}

- (void)disableSwipe {
[_scrollView setScrollEnabled:false];
}

- (void)enableSwipe {
[_scrollView setScrollEnabled:true];
}

- (void)goTo:(NSInteger)index animated:(BOOL)animated {
CGPoint targetOffset = [self isHorizontal] ? CGPointMake(_scrollView.frame.size.width * index, 0) : CGPointMake(0, _scrollView.frame.size.height * index);

if (animated) {
self.animating = true;
}

[_scrollView setContentOffset:targetOffset animated:animated];

if (!animated) {
int position = [self getCurrentPage];
[self.eventDispatcher sendEvent:[[RCTOnPageSelected alloc] initWithReactTag:self.reactTag position:[NSNumber numberWithInt:position] coalescingKey:_coalescingKey++]];
}
}

- (BOOL)isHorizontal {
return [_orientation isEqualToString:@"horizontal"];
}

-(int)getCurrentPage {
return [self isHorizontal] ? _scrollView.contentOffset.x / _scrollView.frame.size.width : _scrollView.contentOffset.y / _scrollView.frame.size.height;
}

#pragma mark - UIScrollViewDelegate


- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self.eventDispatcher sendEvent:[[RCTOnPageScrollStateChanged alloc] initWithReactTag:self.reactTag state:@"dragging" coalescingKey:_coalescingKey++]];
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
[self.eventDispatcher sendEvent:[[RCTOnPageScrollStateChanged alloc] initWithReactTag:self.reactTag state:@"settling" coalescingKey:_coalescingKey++]];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
int position = [self getCurrentPage];
[self.eventDispatcher sendEvent:[[RCTOnPageScrollStateChanged alloc] initWithReactTag:self.reactTag state:@"idle" coalescingKey:_coalescingKey++]];

[self.eventDispatcher sendEvent:[[RCTOnPageSelected alloc] initWithReactTag:self.reactTag position:[NSNumber numberWithInt:position] coalescingKey:_coalescingKey++]];
}

-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
int position = [self getCurrentPage];
self.animating = false;
[self.eventDispatcher sendEvent:[[RCTOnPageSelected alloc] initWithReactTag:self.reactTag position:[NSNumber numberWithInt:position] coalescingKey:_coalescingKey++]];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
int position = [self getCurrentPage];

double offset = [self isHorizontal] ? (scrollView.contentOffset.x - (scrollView.frame.size.width * position))/scrollView.frame.size.width : (scrollView.contentOffset.y - (scrollView.frame.size.height * position))/scrollView.frame.size.height;

[self.eventDispatcher sendEvent:[[RCTOnPageScrollEvent alloc] initWithReactTag:self.reactTag position:@(position) offset:@(offset)]];
}
@end

4 changes: 2 additions & 2 deletions ios/ReactViewPagerManager.h → ios/RNCPagerViewManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
#import <React/RCTViewManager.h>
#import <React/RCTUIManager.h>
#import <React/RCTLog.h>
#import "ReactNativePageView.h"
#import "RNCPagerView.h"
NS_ASSUME_NONNULL_BEGIN

@interface ReactViewPagerManager : RCTViewManager
@interface RNCPagerViewManager : RCTViewManager

@end

Expand Down
22 changes: 10 additions & 12 deletions ios/ReactViewPagerManager.m → ios/RNCPagerViewManager.m
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@

#import "ReactViewPagerManager.h"
#import "RNCPagerViewManager.h"

@implementation ReactViewPagerManager
@implementation RNCPagerViewManager

#pragma mark - RTC

RCT_EXPORT_MODULE(RNCViewPager)

RCT_EXPORT_VIEW_PROPERTY(initialPage, NSInteger)
RCT_EXPORT_VIEW_PROPERTY(pageMargin, NSInteger)
RCT_EXPORT_VIEW_PROPERTY(orientation, NSString)

RCT_EXPORT_VIEW_PROPERTY(orientation, UIPageViewControllerNavigationOrientation)
RCT_EXPORT_VIEW_PROPERTY(onPageSelected, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onPageScroll, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onPageScrollStateChanged, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(overdrag, BOOL)
RCT_EXPORT_VIEW_PROPERTY(layoutDirection, NSString)


- (void) goToPage
Expand All @@ -25,8 +23,8 @@ - (void) goToPage
[self.bridge.uiManager addUIBlock:^(
RCTUIManager *uiManager,
NSDictionary<NSNumber *, UIView *> *viewRegistry) {
ReactNativePageView *view = (ReactNativePageView *)viewRegistry[reactTag];
if (!view || ![view isKindOfClass:[ReactNativePageView class]]) {
RNCPagerView *view = (RNCPagerView *)viewRegistry[reactTag];
if (!view || ![view isKindOfClass:[RNCPagerView class]]) {
RCTLogError(@"Cannot find ReactNativePageView with tag #%@", reactTag);
return;
}
Expand All @@ -42,8 +40,8 @@ - (void) changeScrollEnabled
[self.bridge.uiManager addUIBlock:^(
RCTUIManager *uiManager,
NSDictionary<NSNumber *, UIView *> *viewRegistry) {
ReactNativePageView *view = (ReactNativePageView *)viewRegistry[reactTag];
if (!view || ![view isKindOfClass:[ReactNativePageView class]]) {
RNCPagerView *view = (RNCPagerView *)viewRegistry[reactTag];
if (!view || ![view isKindOfClass:[RNCPagerView class]]) {
RCTLogError(@"Cannot find ReactNativePageView with tag #%@", reactTag);
return;
}
Expand All @@ -70,17 +68,17 @@ - (void) changeScrollEnabled
[self changeScrollEnabled:reactTag enabled:isEnabled];
}

RCT_CUSTOM_VIEW_PROPERTY(scrollEnabled, BOOL, ReactNativePageView) {
RCT_CUSTOM_VIEW_PROPERTY(scrollEnabled, BOOL, RNCPagerView) {
[view shouldScroll:[RCTConvert BOOL:json]];
}

RCT_CUSTOM_VIEW_PROPERTY(keyboardDismissMode, NSString, ReactNativePageView) {
RCT_CUSTOM_VIEW_PROPERTY(keyboardDismissMode, NSString, RNCPagerView) {
[view shouldDismissKeyboard:[RCTConvert NSString:json]];
}


- (UIView *)view {
return [[ReactNativePageView alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
return [[RNCPagerView alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
}

@end
Loading