Skip to content

Commit

Permalink
feat(ios): pageIndex of ViewPager auto update after data changes
Browse files Browse the repository at this point in the history
Also fixed the issue of missing onPageSelected callbacks upon first entry;

The logic for automatic updates keep same with Android, as follows
1. If the previous item only changes its location,
update the current location and keep the current item displayed.
2. If the previous item does not exist, do not adjust the position,
but keep the current position in the valid range (that is, 0 ~ count-1).
  • Loading branch information
wwwcg authored and hippy-actions[bot] committed May 15, 2024
1 parent 78cf381 commit 9545568
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions ios/sdk/component/viewPager/HippyViewPager.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ @interface HippyViewPager ()
@property (nonatomic, assign) CGFloat previousStopOffset;
@property (nonatomic, assign) NSUInteger lastPageSelectedCallbackIndex;

/// A weak property used to record the currently displayed item,
/// which is used for updating the page index when the data changes.
@property (nonatomic, weak) UIView *lastSelectedPageItem;

@end

@implementation HippyViewPager
Expand All @@ -60,6 +64,7 @@ - (instancetype)initWithFrame:(CGRect)frame {
self.previousFrame = CGRectZero;
self.scrollViewListener = [NSHashTable weakObjectsHashTable];
self.lastPageIndex = NSUIntegerMax;
self.lastPageSelectedCallbackIndex = NSUIntegerMax;
self.targetContentOffsetX = CGFLOAT_MAX;
if (@available(iOS 11.0, *)) {
self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
Expand Down Expand Up @@ -153,6 +158,7 @@ - (void)setPage:(NSInteger)pageNumber animated:(BOOL)animated {

_lastPageIndex = pageNumber;
UIView *theItem = self.viewPagerItems[pageNumber];
self.lastSelectedPageItem = theItem;
self.targetContentOffsetX = CGRectGetMinX(theItem.frame);
[self setContentOffset:theItem.frame.origin animated:animated];
[self invokePageSelected:pageNumber];
Expand Down Expand Up @@ -335,6 +341,7 @@ - (NSUInteger)targetPageIndexFromTargetContentOffsetX:(CGFloat)targetContentOffs
}
if (_lastPageIndex != thePage) {
_lastPageIndex = thePage;
_lastSelectedPageItem = self.viewPagerItems[thePage];
return thePage;
} else {
return _lastPageIndex;
Expand Down Expand Up @@ -362,6 +369,23 @@ - (void)hippyBridgeDidFinishTransaction {
BOOL isFrameEqual = CGRectEqualToRect(self.frame, self.previousFrame);
BOOL isContentSizeEqual = CGSizeEqualToSize(self.contentSize, self.previousSize);

if (!isContentSizeEqual) {
// Update the latest page index based on the currently displayed item (aka lastSelectedPageItem).
// Keep the same logic as android:
// 1. If the previous item only changes its location,
// update the current location and keep the current item displayed.
// 2. If the previous item does not exist, do not adjust the position,
// but keep the current position in the valid range (that is, 0 ~ count-1).
UIView *previousSelectedItem = self.lastSelectedPageItem;
NSUInteger updatedPageIndex;
if (previousSelectedItem) {
updatedPageIndex = [self.viewPagerItems indexOfObject:previousSelectedItem];
} else {
updatedPageIndex = MAX(0, MIN(self.lastPageIndex, self.viewPagerItems.count - 1));
}
self.lastPageIndex = updatedPageIndex;
self.needsResetPageIndex = YES;
}
if (!isContentSizeEqual || !isFrameEqual) {
self.previousFrame = self.frame;
self.previousSize = self.contentSize;
Expand Down

0 comments on commit 9545568

Please sign in to comment.