Skip to content

Commit

Permalink
fix(ios): fix viewpager onpagescroll and onpageselected event (#761)
Browse files Browse the repository at this point in the history
* fix(ios): fix viewpager onpagescroll and onpageselected event
  • Loading branch information
ozonelmy authored and zoomchan-cxj committed May 19, 2021
1 parent c3da871 commit 1a50294
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 40 deletions.
105 changes: 65 additions & 40 deletions ios/sdk/component/viewPager/HippyViewPager.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ @interface HippyViewPager ()
@property (nonatomic, strong) NSMutableArray<UIView *> *viewPagerItems;
@property (nonatomic, assign) BOOL isScrolling;
@property (nonatomic, assign) BOOL loadOnce;
@property (nonatomic, assign) NSInteger pageOfBeginDragging;

@property (nonatomic, assign) CGRect previousFrame;
@property (nonatomic, assign) CGSize previousSize;
Expand All @@ -41,6 +40,9 @@ @interface HippyViewPager ()
@property (nonatomic, assign) BOOL needsLayoutItems;
@property (nonatomic, assign) BOOL needsResetPageIndex;

@property (nonatomic, assign) CGFloat previousStopOffset;
@property (nonatomic, assign) NSUInteger lastPageSelectedCallbackIndex;

@end

@implementation HippyViewPager
Expand Down Expand Up @@ -141,9 +143,7 @@ - (void)setPage:(NSInteger)pageNumber animated:(BOOL)animated {
UIView *theItem = self.viewPagerItems[pageNumber];
self.targetContentOffsetX = CGRectGetMinX(theItem.frame);
[self setContentOffset:theItem.frame.origin animated:animated];
if (self.onPageSelected) {
self.onPageSelected(@{ @"position": @(pageNumber) });
}
[self invokePageSelected:pageNumber];
if (self.onPageScrollStateChanged) {
self.onPageScrollStateChanged(@{ @"pageScrollState": @"idle" });
}
Expand All @@ -155,32 +155,34 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSString *state = scrollView.isDragging ? @"dragging" : @"settling";
self.onPageScrollStateChanged(@{ @"pageScrollState": state });
}
NSInteger beforePage = self.pageOfBeginDragging;
CGFloat commonPagerWidth = [self commonPagerWidth];
CGFloat beforeOffsetX = beforePage * commonPagerWidth;
CGFloat nowContentOffsetX = self.contentOffset.x;
CGFloat betweenOffset = nowContentOffsetX - beforeOffsetX;
CGFloat offsetRate = betweenOffset / commonPagerWidth;
if (offsetRate != 0) {
NSInteger nowPage = 0;
if (CGFLOAT_MAX == self.targetContentOffsetX) {
nowPage = offsetRate < 0 ? beforePage - 1 : beforePage + 1; //-1 for left slide,1 for right;
if (nowPage == -1) {
nowPage = 0;
}
if (nowPage == self.viewPagerItems.count) {
nowPage = self.viewPagerItems.count - 1;
}
} else {
nowPage = [self targetPageIndexFromTargetContentOffsetX:self.targetContentOffsetX];
}
if (self.onPageScroll) {
self.onPageScroll(@{
@"position": @(nowPage),
@"offset": @(offsetRate),
});
}

CGFloat currentContentOffset = self.contentOffset.x;
CGFloat offset = currentContentOffset - self.previousStopOffset;
CGFloat offsetRatio = offset / CGRectGetWidth(self.bounds);

if (offsetRatio > 1) {
offsetRatio -= floor(offsetRatio);
}
if (offsetRatio < -1) {
offsetRatio -= ceil(offsetRatio);
}

NSUInteger currentPageIndex = [self currentPageIndex];
NSInteger nextPageIndex = ceil(offsetRatio) == offsetRatio ? currentPageIndex : currentPageIndex + ceil(offsetRatio);
if (nextPageIndex < 0) {
nextPageIndex = 0;
}
if (nextPageIndex >= [self.viewPagerItems count]) {
nextPageIndex = [self.viewPagerItems count] - 1;
}

if (self.onPageScroll) {
self.onPageScroll(@{
@"position": @(nextPageIndex),
@"offset": @(offsetRatio),
});
}

for (NSObject<UIScrollViewDelegate> *scrollViewListener in _scrollViewListener) {
if ([scrollViewListener respondsToSelector:@selector(scrollViewDidScroll:)]) {
[scrollViewListener scrollViewDidScroll:scrollView];
Expand All @@ -190,7 +192,6 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {

//用户拖拽的开始,也是整个滚动流程的开始
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
self.pageOfBeginDragging = self.nowPage;
self.isScrolling = YES;
self.targetContentOffsetX = CGFLOAT_MAX;
for (NSObject<UIScrollViewDelegate> *scrollViewListener in _scrollViewListener) {
Expand All @@ -203,9 +204,7 @@ - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
self.targetContentOffsetX = targetContentOffset->x;
NSUInteger page = [self targetPageIndexFromTargetContentOffsetX:self.targetContentOffsetX];
if (self.onPageSelected) {
self.onPageSelected(@{ @"position": @(page) });
}
[self invokePageSelected:page];
for (NSObject<UIScrollViewDelegate> *scrollViewListener in _scrollViewListener) {
if ([scrollViewListener respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
[scrollViewListener scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
Expand All @@ -219,6 +218,9 @@ - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL
[scrollViewListener scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
}
}
if (!decelerate) {
self.isScrolling = NO;
}
}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView {
Expand Down Expand Up @@ -257,6 +259,10 @@ - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView {
}
}

- (void)scrollViewDidEndScrolling {
self.previousStopOffset = [self contentOffset].x;
}

#pragma mark scrollview listener methods
- (void)addScrollListener:(id<UIScrollViewDelegate>)scrollListener {
[_scrollViewListener addObject:scrollListener];
Expand All @@ -267,6 +273,32 @@ - (void)removeScrollListener:(id<UIScrollViewDelegate>)scrollListener {
}

#pragma mark other methods
- (NSUInteger)currentPageIndex {
return [self pageIndexForContentOffset:self.contentOffset.x];
}

- (NSUInteger)pageIndexForContentOffset:(CGFloat)offset {
CGFloat pageWidth = CGRectGetWidth(self.bounds);
NSUInteger page = floor(offset / pageWidth);
return page;
}

- (void)setIsScrolling:(BOOL)isScrolling {
if (!isScrolling) {
[self scrollViewDidEndScrolling];
}
_isScrolling = isScrolling;
}

- (void)invokePageSelected:(NSUInteger)index {
if (self.onPageSelected &&
self.lastPageSelectedCallbackIndex != index &&
index < [[self viewPagerItems] count]) {
self.lastPageSelectedCallbackIndex = index;
self.onPageSelected(@{ @"position": @(index)});
}
}

- (NSUInteger)targetPageIndexFromTargetContentOffsetX:(CGFloat)targetContentOffsetX {
NSInteger thePage = -1;
if (fabs(targetContentOffsetX) < FLT_EPSILON) {
Expand Down Expand Up @@ -308,13 +340,6 @@ - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated {
[super setContentOffset:contentOffset animated:animated];
}

- (CGFloat)commonPagerWidth {
if ([self.viewPagerItems count] == 0) {
return self.frame.size.width;
}
return self.viewPagerItems[0].frame.size.width;
}

- (void)hippyBridgeDidFinishTransaction {
BOOL isFrameEqual = CGRectEqualToRect(self.frame, self.previousFrame);
BOOL isContentSizeEqual = CGSizeEqualToSize(self.contentSize, self.previousSize);
Expand Down
1 change: 1 addition & 0 deletions ios/sdk/component/viewPager/HippyViewPagerManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ - (UIView *)view {
HIPPY_EXPORT_VIEW_PROPERTY(onPageSelected, HippyDirectEventBlock)
HIPPY_EXPORT_VIEW_PROPERTY(onPageScroll, HippyDirectEventBlock)
HIPPY_EXPORT_VIEW_PROPERTY(onPageScrollStateChanged, HippyDirectEventBlock)
HIPPY_EXPORT_VIEW_PROPERTY(bounces, BOOL)

// clang-format off
HIPPY_EXPORT_METHOD(setPage:(nonnull NSNumber *)hippyTag
Expand Down

0 comments on commit 1a50294

Please sign in to comment.