|
| 1 | + |
| 2 | +#import "RNCPagerView.h" |
| 3 | +#import "React/RCTLog.h" |
| 4 | +#import <React/RCTViewManager.h> |
| 5 | + |
| 6 | +#import "UIViewController+CreateExtension.h" |
| 7 | +#import "RCTOnPageScrollEvent.h" |
| 8 | +#import "RCTOnPageScrollStateChanged.h" |
| 9 | +#import "React/RCTUIManagerObserverCoordinator.h" |
| 10 | +#import "RCTOnPageSelected.h" |
| 11 | +#import <math.h> |
| 12 | + |
| 13 | +@interface RNCPagerView () <UIScrollViewDelegate> |
| 14 | + |
| 15 | +@property(nonatomic, strong) id<RCTEventDispatcherProtocol> eventDispatcher; |
| 16 | + |
| 17 | +@property(nonatomic, strong) UIScrollView *scrollView; |
| 18 | +@property(nonatomic, strong) UIView *containerView; |
| 19 | + |
| 20 | +- (void)goTo:(NSInteger)index animated:(BOOL)animated; |
| 21 | +- (void)shouldScroll:(BOOL)scrollEnabled; |
| 22 | +- (void)shouldDismissKeyboard:(NSString *)dismissKeyboard; |
| 23 | + |
| 24 | +@end |
| 25 | + |
| 26 | +@implementation RNCPagerView { |
| 27 | + uint16_t _coalescingKey; |
| 28 | +} |
| 29 | + |
| 30 | +- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher { |
| 31 | + if (self = [super init]) { |
| 32 | + _initialPage = 0; |
| 33 | + _dismissKeyboard = UIScrollViewKeyboardDismissModeNone; |
| 34 | + _coalescingKey = 0; |
| 35 | + _eventDispatcher = eventDispatcher; |
| 36 | + _orientation = @"horizontal"; |
| 37 | + [self embed]; |
| 38 | + } |
| 39 | + return self; |
| 40 | +} |
| 41 | + |
| 42 | +- (void)layoutSubviews { |
| 43 | + [super layoutSubviews]; |
| 44 | + [self calculateContentSize]; |
| 45 | +} |
| 46 | + |
| 47 | +- (void)didUpdateReactSubviews { |
| 48 | + [self calculateContentSize]; |
| 49 | +} |
| 50 | + |
| 51 | +-(void) insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex { |
| 52 | + [super insertReactSubview:subview atIndex:atIndex]; |
| 53 | + [_containerView insertSubview:subview atIndex:atIndex]; |
| 54 | +} |
| 55 | + |
| 56 | +- (void)removeReactSubview:(UIView *)subview { |
| 57 | + [super removeReactSubview:subview]; |
| 58 | + [subview removeFromSuperview]; |
| 59 | + |
| 60 | + if ([self getCurrentPage] >= self.reactSubviews.count - 1) { |
| 61 | + [self goTo:self.reactSubviews.count - 1 animated:false]; |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +- (void)embed { |
| 66 | + _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; |
| 67 | + _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; |
| 68 | + _scrollView.delaysContentTouches = NO; |
| 69 | + _scrollView.delegate = self; |
| 70 | + _scrollView.pagingEnabled = YES; |
| 71 | + _scrollView.showsHorizontalScrollIndicator = NO; |
| 72 | + _scrollView.showsVerticalScrollIndicator = NO; |
| 73 | + [self addSubview:_scrollView]; |
| 74 | + |
| 75 | + _containerView = [[UIView alloc] initWithFrame:self.bounds]; |
| 76 | + [_scrollView addSubview:_containerView]; |
| 77 | +} |
| 78 | + |
| 79 | +- (void)didSetProps:(NSArray<NSString *> *)changedProps { |
| 80 | + if ([changedProps containsObject:@"overdrag"]) { |
| 81 | + [_scrollView setBounces:_overdrag]; |
| 82 | + } |
| 83 | +} |
| 84 | + |
| 85 | +- (void)shouldScroll:(BOOL)scrollEnabled { |
| 86 | + if (self.scrollView) { |
| 87 | + self.scrollView.scrollEnabled = scrollEnabled; |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +- (void)shouldDismissKeyboard:(NSString *)dismissKeyboard { |
| 92 | + _dismissKeyboard = [dismissKeyboard isEqual: @"on-drag"] ? |
| 93 | + UIScrollViewKeyboardDismissModeOnDrag : UIScrollViewKeyboardDismissModeNone; |
| 94 | + self.scrollView.keyboardDismissMode = _dismissKeyboard; |
| 95 | +} |
| 96 | + |
| 97 | +#pragma mark - Internal methods |
| 98 | + |
| 99 | +- (void) calculateContentSize { |
| 100 | + UIView *initialView = self.containerView.subviews.firstObject; |
| 101 | + if (!initialView) { |
| 102 | + return; |
| 103 | + } |
| 104 | + |
| 105 | + CGFloat totalSubviewsWidth = initialView.frame.size.width * self.containerView.subviews.count; |
| 106 | + CGFloat totalSubviewsHeight = initialView.frame.size.height * self.containerView.subviews.count; |
| 107 | + |
| 108 | + |
| 109 | + if ([self isHorizontal]) { |
| 110 | + _scrollView.contentSize = CGSizeMake(totalSubviewsWidth, 0); |
| 111 | + _containerView.frame = CGRectMake(0, 0, totalSubviewsWidth, initialView.bounds.size.height); |
| 112 | + } else { |
| 113 | + _scrollView.contentSize = CGSizeMake(0, totalSubviewsHeight); |
| 114 | + _containerView.frame = CGRectMake(0, 0, initialView.bounds.size.width, totalSubviewsHeight); |
| 115 | + } |
| 116 | + |
| 117 | + _scrollView.frame = self.bounds; |
| 118 | + [self.scrollView layoutIfNeeded]; |
| 119 | + |
| 120 | + if (self.initialPage != 0) { |
| 121 | + [self goTo:self.initialPage animated:false]; |
| 122 | + } |
| 123 | +} |
| 124 | + |
| 125 | +- (void)disableSwipe { |
| 126 | + [_scrollView setScrollEnabled:false]; |
| 127 | +} |
| 128 | + |
| 129 | +- (void)enableSwipe { |
| 130 | + [_scrollView setScrollEnabled:true]; |
| 131 | +} |
| 132 | + |
| 133 | +- (void)goTo:(NSInteger)index animated:(BOOL)animated { |
| 134 | + CGPoint targetOffset = [self isHorizontal] ? CGPointMake(_scrollView.frame.size.width * index, 0) : CGPointMake(0, _scrollView.frame.size.height * index); |
| 135 | + |
| 136 | + if (animated) { |
| 137 | + self.animating = true; |
| 138 | + } |
| 139 | + |
| 140 | + [_scrollView setContentOffset:targetOffset animated:animated]; |
| 141 | + |
| 142 | + if (!animated) { |
| 143 | + int position = [self getCurrentPage]; |
| 144 | + [self.eventDispatcher sendEvent:[[RCTOnPageSelected alloc] initWithReactTag:self.reactTag position:[NSNumber numberWithInt:position] coalescingKey:_coalescingKey++]]; |
| 145 | + } |
| 146 | +} |
| 147 | + |
| 148 | +- (BOOL)isHorizontal { |
| 149 | + return [_orientation isEqualToString:@"horizontal"]; |
| 150 | +} |
| 151 | + |
| 152 | +-(int)getCurrentPage { |
| 153 | + return [self isHorizontal] ? _scrollView.contentOffset.x / _scrollView.frame.size.width : _scrollView.contentOffset.y / _scrollView.frame.size.height; |
| 154 | +} |
| 155 | + |
| 156 | +#pragma mark - UIScrollViewDelegate |
| 157 | + |
| 158 | + |
| 159 | +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { |
| 160 | + [self.eventDispatcher sendEvent:[[RCTOnPageScrollStateChanged alloc] initWithReactTag:self.reactTag state:@"dragging" coalescingKey:_coalescingKey++]]; |
| 161 | +} |
| 162 | + |
| 163 | +- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { |
| 164 | + [self.eventDispatcher sendEvent:[[RCTOnPageScrollStateChanged alloc] initWithReactTag:self.reactTag state:@"settling" coalescingKey:_coalescingKey++]]; |
| 165 | +} |
| 166 | + |
| 167 | +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { |
| 168 | + int position = [self getCurrentPage]; |
| 169 | + [self.eventDispatcher sendEvent:[[RCTOnPageScrollStateChanged alloc] initWithReactTag:self.reactTag state:@"idle" coalescingKey:_coalescingKey++]]; |
| 170 | + |
| 171 | + [self.eventDispatcher sendEvent:[[RCTOnPageSelected alloc] initWithReactTag:self.reactTag position:[NSNumber numberWithInt:position] coalescingKey:_coalescingKey++]]; |
| 172 | +} |
| 173 | + |
| 174 | +-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { |
| 175 | + int position = [self getCurrentPage]; |
| 176 | + self.animating = false; |
| 177 | + [self.eventDispatcher sendEvent:[[RCTOnPageSelected alloc] initWithReactTag:self.reactTag position:[NSNumber numberWithInt:position] coalescingKey:_coalescingKey++]]; |
| 178 | +} |
| 179 | + |
| 180 | +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { |
| 181 | + int position = [self getCurrentPage]; |
| 182 | + |
| 183 | + 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; |
| 184 | + |
| 185 | + [self.eventDispatcher sendEvent:[[RCTOnPageScrollEvent alloc] initWithReactTag:self.reactTag position:@(position) offset:@(offset)]]; |
| 186 | +} |
| 187 | +@end |
| 188 | + |
0 commit comments