@onekeyfe/react-native-pager-view 3.0.159 → 3.0.161

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/SPEC.md CHANGED
@@ -329,18 +329,22 @@ retained-page switching, clipping and nested-owner cleanup. Programmatic UIKit
329
329
  unit tests do not substitute for real pull-gesture visibility acceptance.
330
330
 
331
331
  When a smooth shared header is attached to the active iOS scroll view, UIKit's
332
- temporary refresh top inset MUST NOT add a second downward displacement to that
333
- header. The pager uses its own applied top inset as the baseline and cancels only
334
- the refresh-added visual displacement. The scroll view's inset and offset, the
335
- refresh indicator, and refresh callback ownership remain unchanged. Removing the
336
- refresh inset or control reapplies the header position immediately, even without
337
- a scroll-offset event. Caller inset changes update the pager baseline before the
338
- header position is reapplied. Detaching the header restores its normal
339
- transform. This applies to RN NativeScroller and NativeList pages; non-smooth
340
- and detached headers keep their existing positioning. The 2026-09-30 Home Spot
341
- simulator checkpoint covers
342
- an active refresh with repeated vertical swipes and subsequent inset removal;
343
- other Home pages and physical-device acceptance remain open.
332
+ temporary refresh top inset MUST keep the header and content aligned. Both are
333
+ children of that scroll view and move together with its content offset; the
334
+ pager MUST NOT apply a separate refresh translation to the header. The scroll
335
+ view's inset and offset, the refresh indicator, and refresh callback ownership
336
+ remain unchanged. Removing the refresh inset or control preserves this alignment
337
+ even without a scroll-offset event. Caller inset changes update the pager
338
+ baseline. The sticky tab row MUST pin against the baseline top inset; the
339
+ refresh control's temporary inset MUST NOT move it below the content, including
340
+ rapid direction reversals while the spinner is active. Detaching the header
341
+ restores its normal transform. This applies to RN NativeScroller and NativeList
342
+ pages; non-smooth and detached headers keep
343
+ their existing positioning. The 2026-09-30 Home Spot simulator checkpoint covers
344
+ shared header/content alignment and inset removal. A separate source-identical
345
+ local package build verified the sticky row during active-refresh vertical
346
+ reversals; published-package, other Home pages and physical-device acceptance
347
+ remain open.
344
348
 
345
349
  ## iOS shared-header hit testing
346
350
 
@@ -3042,16 +3042,15 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
3042
3042
  BOOL attachedToList = _nativeSmoothHeaderScrollEnabled &&
3043
3043
  _sharedHeaderScrollView != nil && !_sharedHeadersLiftedForPagerTransition;
3044
3044
  if (attachedToList) {
3045
- // UIRefreshControl temporarily adds a top inset while refreshing. The
3046
- // shared header lives in that scroll view, so exclude only that inset from
3047
- // its visual position while keeping the list's pull and indicator intact.
3048
- NSNumber *pagerTopInset = [_appliedTopInsets objectForKey:_sharedHeaderScrollView];
3049
- CGFloat refreshInset = _sharedHeaderScrollView.refreshControl != nil && pagerTopInset != nil
3050
- ? MAX(0, _sharedHeaderScrollView.contentInset.top - pagerTopInset.doubleValue)
3051
- : 0;
3052
- _sharedHeaderHostView.transform = CGAffineTransformMakeTranslation(0, -refreshInset);
3045
+ // The header and content share this scroll view. UIKit's refresh inset
3046
+ // moves both together, so translating the header would separate them.
3047
+ _sharedHeaderHostView.transform = CGAffineTransformIdentity;
3053
3048
  _headerView.transform = CGAffineTransformIdentity;
3054
- CGFloat pinnedTranslation = MAX(0, _currentLogicalOffset - _headerHeight);
3049
+ UIScrollView *scrollView = _sharedHeaderScrollView;
3050
+ NSNumber *appliedTop = [_appliedTopInsets objectForKey:scrollView];
3051
+ CGFloat refreshInset = scrollView.refreshControl != nil && appliedTop != nil
3052
+ ? MAX(0, scrollView.contentInset.top - appliedTop.doubleValue) : 0;
3053
+ CGFloat pinnedTranslation = MAX(0, _currentLogicalOffset - _headerHeight - refreshInset);
3055
3054
  CGAffineTransform stickyTransform = CGAffineTransformMakeTranslation(0, pinnedTranslation);
3056
3055
  _stickyHeaderView.transform = stickyTransform;
3057
3056
  _nativeTabBarView.transform = stickyTransform;
@@ -185,27 +185,36 @@
185
185
  scroll.refreshControl = [UIRefreshControl new];
186
186
  scroll.contentSize = CGSizeMake(320, 2000);
187
187
  scroll.contentInset = UIEdgeInsetsMake(232, 0, 0, 0);
188
+ UIView *content = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 2000)];
189
+ [scroll addSubview:content];
188
190
  UIViewController *page = [UIViewController new];
189
191
  [page.view addSubview:scroll];
190
192
  NSMutableArray<UIViewController *> *pages = [pager valueForKey:@"pageControllers"];
191
193
  [pages addObject:page];
192
194
  [pager attachScrollObserverForCurrentPage];
193
195
  UIView *headerHost = [pager valueForKey:@"sharedHeaderHostView"];
196
+ UIView *stickyHeader = [pager valueForKey:@"stickyHeaderView"];
194
197
  XCTAssertEqual(headerHost.superview, scroll);
195
198
  XCTAssertEqualWithAccuracy(scroll.contentInset.top, 340, 0.001);
196
199
  XCTAssertEqualWithAccuracy(headerHost.transform.ty, 0, 0.001);
197
200
 
198
201
  scroll.contentOffset = CGPointMake(0, 500);
202
+ CGFloat baselineStickyTranslation = stickyHeader.transform.ty;
199
203
  CGPoint offset = scroll.contentOffset;
200
204
  scroll.contentInset = UIEdgeInsetsMake(400, 0, 0, 0);
201
205
  XCTAssertTrue(CGPointEqualToPoint(scroll.contentOffset, offset));
202
- XCTAssertEqualWithAccuracy(headerHost.transform.ty, -60, 0.001);
206
+ XCTAssertEqualWithAccuracy(headerHost.transform.ty, 0, 0.001);
207
+ XCTAssertEqualWithAccuracy(stickyHeader.transform.ty, baselineStickyTranslation, 0.001);
208
+ XCTAssertEqualWithAccuracy(CGRectGetMaxY(headerHost.frame), CGRectGetMinY(content.frame), 0.001);
203
209
 
204
210
  scroll.contentInset = UIEdgeInsetsMake(340, 0, 0, 0);
205
211
  XCTAssertEqualWithAccuracy(headerHost.transform.ty, 0, 0.001);
212
+ XCTAssertEqualWithAccuracy(stickyHeader.transform.ty, baselineStickyTranslation, 0.001);
206
213
 
207
214
  scroll.contentInset = UIEdgeInsetsMake(400, 0, 0, 0);
208
- XCTAssertEqualWithAccuracy(headerHost.transform.ty, -60, 0.001);
215
+ XCTAssertEqualWithAccuracy(headerHost.transform.ty, 0, 0.001);
216
+ XCTAssertEqualWithAccuracy(stickyHeader.transform.ty, baselineStickyTranslation, 0.001);
217
+ XCTAssertEqualWithAccuracy(CGRectGetMaxY(headerHost.frame), CGRectGetMinY(content.frame), 0.001);
209
218
  scroll.refreshControl = nil;
210
219
  XCTAssertEqualWithAccuracy(headerHost.transform.ty, 0, 0.001);
211
220
  [pager prepareForRecycle];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-pager-view",
3
- "version": "3.0.159",
3
+ "version": "3.0.161",
4
4
  "description": "React Native wrapper for Android and iOS ViewPager",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/module/index.js",
@@ -69,7 +69,7 @@
69
69
  "typescript": "^5.9.2"
70
70
  },
71
71
  "peerDependencies": {
72
- "@onekeyfe/react-native-native-logger": "3.0.159",
72
+ "@onekeyfe/react-native-native-logger": "3.0.161",
73
73
  "react": "*",
74
74
  "react-native": "*"
75
75
  },