diff --git a/ios/sdk/component/viewPager/HippyViewPager.m b/ios/sdk/component/viewPager/HippyViewPager.m index cc7e4b407a3..b861668b5f3 100644 --- a/ios/sdk/component/viewPager/HippyViewPager.m +++ b/ios/sdk/component/viewPager/HippyViewPager.m @@ -140,10 +140,12 @@ - (void)removeHippySubview:(UIView *)subview { } - (void)hippySetFrame:(CGRect)frame { - [super hippySetFrame:frame]; - self.needsLayoutItems = YES; - self.needsResetPageIndex = YES; - [self setNeedsLayout]; + if (!CGRectEqualToRect(self.bounds, frame)) { + [super hippySetFrame:frame]; + self.needsLayoutItems = YES; + self.needsResetPageIndex = YES; + [self setNeedsLayout]; + } } - (void)didUpdateHippySubviews { @@ -189,14 +191,18 @@ - (void)setPage:(NSInteger)pageNumber animated:(BOOL)animated { [self setContentOffset:theItem.frame.origin animated:animated]; [self invokePageSelected:pageNumber]; - if (self.onPageScrollStateChanged) { - if (animated) { + if (animated) { + if (self.onPageScrollStateChanged) { HippyLogTrace(@"[HippyViewPager] settling --- (setPage withAnimation)"); self.onPageScrollStateChanged(@{ HippyPageScrollStateKey: HippyPageScrollStateSettling }); - } else { + } + } else { + if (self.onPageScrollStateChanged) { HippyLogTrace(@"[HippyViewPager] idle ~~~~~~ (setPage withoutAnimation)"); self.onPageScrollStateChanged(@{ HippyPageScrollStateKey: HippyPageScrollStateIdle }); } + // Record stop offset for onPageScroll callback + [self recordScrollStopOffsetX]; } } @@ -204,11 +210,17 @@ - (void)setPage:(NSInteger)pageNumber animated:(BOOL)animated { - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat currentContentOffset = self.contentOffset.x; + CGFloat pageWidth = CGRectGetWidth(self.bounds); CGFloat offset = currentContentOffset - self.previousStopOffset; - CGFloat offsetRatio = fmod((offset / CGRectGetWidth(self.bounds)), 1.0 + DBL_EPSILON); + CGFloat offsetRatio = fmod((offset / pageWidth), 1.0 + DBL_EPSILON); + + // get current base page index + NSUInteger currentPageIndex = floor(currentContentOffset / pageWidth); - NSUInteger currentPageIndex = [self currentPageIndex]; - NSInteger nextPageIndex = ceil(offsetRatio) == offsetRatio ? currentPageIndex : currentPageIndex + ceil(offsetRatio); + // If offsetRatio is 1.0, then currentPageIndex is nextPageIndex, else nextPageIndex add/subtract 1. + // The theoretical maximum gap is 2 DBL_EPSILON, take 10 to allow for some redundancy. + BOOL isRatioEqualTo1 = (fabs(ceil(offsetRatio) - offsetRatio) < 10 * DBL_EPSILON); + NSInteger nextPageIndex = isRatioEqualTo1 ? currentPageIndex : currentPageIndex + ceil(offsetRatio); if (nextPageIndex < 0) { nextPageIndex = 0; } else if (nextPageIndex >= [self.viewPagerItems count]) { @@ -216,6 +228,8 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { } if (self.onPageScroll) { + HippyLogTrace(@"[HippyViewPager] CurrentPage:%ld NextPage:%ld Ratio:%f, %f-%f-%f", + currentPageIndex, nextPageIndex, offsetRatio, pageWidth, currentContentOffset, offset); self.onPageScroll(@{ @"position": @(nextPageIndex), @"offset": @(offsetRatio), @@ -229,7 +243,6 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { } } -//用户拖拽的开始,也是整个滚动流程的开始 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { self.isScrolling = YES; self.targetContentOffsetX = CGFLOAT_MAX; @@ -323,6 +336,7 @@ - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { + self.isScrolling = NO; if (self.onPageScrollStateChanged) { HippyLogTrace(@"[HippyViewPager] idle ~~~~~~ (DidEndScrollingAnimation)"); self.onPageScrollStateChanged(@{ HippyPageScrollStateKey : HippyPageScrollStateIdle }); @@ -343,8 +357,11 @@ - (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView { } } -- (void)scrollViewDidEndScrolling { - self.previousStopOffset = [self contentOffset].x; +- (void)recordScrollStopOffsetX { + // Delay a bit to avoid recording offset of unfinished state + dispatch_async(dispatch_get_main_queue(), ^{ + self.previousStopOffset = [self contentOffset].x; + }); } #pragma mark scrollview listener methods @@ -369,7 +386,7 @@ - (NSUInteger)pageIndexForContentOffset:(CGFloat)offset { - (void)setIsScrolling:(BOOL)isScrolling { if (!isScrolling) { - [self scrollViewDidEndScrolling]; + [self recordScrollStopOffsetX]; } _isScrolling = isScrolling; }