Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ios): improve accuracy of ViewPager's onPageScroll parameters #3992

Merged
merged 2 commits into from
Aug 13, 2024
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
45 changes: 31 additions & 14 deletions ios/sdk/component/viewPager/HippyViewPager.m
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -189,33 +191,45 @@ - (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];
}
}

#pragma mark scrollview delegate methods
- (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]) {
nextPageIndex = [self.viewPagerItems count] - 1;
}

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),
Expand All @@ -229,7 +243,6 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
}
}

//用户拖拽的开始,也是整个滚动流程的开始
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
self.isScrolling = YES;
self.targetContentOffsetX = CGFLOAT_MAX;
Expand Down Expand Up @@ -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 });
Expand All @@ -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
Expand All @@ -369,7 +386,7 @@ - (NSUInteger)pageIndexForContentOffset:(CGFloat)offset {

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