@onekeyfe/react-native-pager-view 6.7.0-alpha.428 → 6.7.0-alpha.432
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.
|
@@ -185,6 +185,25 @@ struct RNCScrollCandidateResolution {
|
|
|
185
185
|
@implementation RNCCollapsiblePagerReleasedScrollState
|
|
186
186
|
@end
|
|
187
187
|
|
|
188
|
+
@interface RNCCollapsiblePagerTransitionEdgeOwner : NSObject
|
|
189
|
+
@property (nonatomic, weak) UIScrollView *scrollView;
|
|
190
|
+
@property (nonatomic, weak) UIView *page;
|
|
191
|
+
@property (nonatomic, strong) UIScrollEdgeEffectStyle *originalStyle;
|
|
192
|
+
@property (nonatomic, strong) UIScrollEdgeElementContainerInteraction *topInteraction;
|
|
193
|
+
@property (nonatomic, strong) UIScrollEdgeElementContainerInteraction *stickyInteraction;
|
|
194
|
+
@property (nonatomic, weak) UIView *topHost;
|
|
195
|
+
@property (nonatomic, weak) UIView *stickyHost;
|
|
196
|
+
@property (nonatomic, strong) UILabel *topMarker;
|
|
197
|
+
@property (nonatomic, strong) UILabel *stickyMarker;
|
|
198
|
+
@property (nonatomic, assign) BOOL borrowsPinnedStickyHost;
|
|
199
|
+
@property (nonatomic, assign) BOOL ownsTransitionHosts;
|
|
200
|
+
@property (nonatomic, strong) UIView *ownedTopHost;
|
|
201
|
+
@property (nonatomic, strong) UIView *ownedStickyHost;
|
|
202
|
+
@end
|
|
203
|
+
|
|
204
|
+
@implementation RNCCollapsiblePagerTransitionEdgeOwner
|
|
205
|
+
@end
|
|
206
|
+
|
|
188
207
|
static UIView *RNCScrollComponentView(UIScrollView *scrollView)
|
|
189
208
|
{
|
|
190
209
|
for (UIView *view = scrollView; view != nil; view = view.superview) {
|
|
@@ -1526,6 +1545,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1526
1545
|
RNCPagerViewNestedOverlayObserver
|
|
1527
1546
|
>
|
|
1528
1547
|
- (void)finishPagerScrollEmittingSelection:(BOOL)emitSelection;
|
|
1548
|
+
- (void)cancelPendingNativePagerScroll;
|
|
1529
1549
|
- (void)completeTransitionOnNextRunLoopForGeneration:(NSUInteger)generation
|
|
1530
1550
|
transition:(NSUInteger)transition;
|
|
1531
1551
|
- (void)setDirectNativePagerEnabled:(BOOL)enabled;
|
|
@@ -1556,6 +1576,15 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1556
1576
|
- (void)syncScrollEdgeAppearance;
|
|
1557
1577
|
- (void)updateHardEdgeSeparatorCovers;
|
|
1558
1578
|
- (void)updateTopOverlayThemeBackground;
|
|
1579
|
+
- (BOOL)canPreserveHorizontalScrollEdgesAllowExternalOverlay:(BOOL)allowExternalOverlay;
|
|
1580
|
+
- (void)beginProgrammaticScrollEdgesToIndex:(NSInteger)index allowExternalOverlay:(BOOL)allowExternalOverlay;
|
|
1581
|
+
- (void)adoptCurrentScrollEdgeForProgrammaticTransition:(BOOL)allowExternalOverlay;
|
|
1582
|
+
- (RNCCollapsiblePagerTransitionEdgeOwner *)borrowedPinnedStickyOwner;
|
|
1583
|
+
- (void)releaseProgrammaticScrollEdge:(UIScrollView *)scrollView;
|
|
1584
|
+
- (void)releaseProgrammaticScrollEdgeOwner:(RNCCollapsiblePagerTransitionEdgeOwner *)owner;
|
|
1585
|
+
- (void)clearProgrammaticScrollEdges;
|
|
1586
|
+
- (void)finishProgrammaticScrollEdges;
|
|
1587
|
+
- (BOOL)hasProgrammaticScrollEdgeForPage:(UIView *)page;
|
|
1559
1588
|
- (void)updateScrollEdgeContentMasks;
|
|
1560
1589
|
- (void)restoreScrollEdgeContentMasks;
|
|
1561
1590
|
- (void)sharedHeaderPressCancellationGestureChanged:(UIPanGestureRecognizer *)recognizer;
|
|
@@ -1639,6 +1668,13 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1639
1668
|
BOOL _hasPendingDirectNativePagerChange;
|
|
1640
1669
|
BOOL _hasReceivedPageCommand;
|
|
1641
1670
|
NSUInteger _transitionId;
|
|
1671
|
+
void (^_pendingNativePagerScrollCompletion)(BOOL);
|
|
1672
|
+
NSUInteger _pendingNativePagerScrollGeneration;
|
|
1673
|
+
NSUInteger _pendingNativePagerScrollTransition;
|
|
1674
|
+
CGFloat _pendingNativePagerScrollTarget;
|
|
1675
|
+
NSIndexSet *_programmaticPageMaskIndexes;
|
|
1676
|
+
NSMapTable<UIScrollView *, RNCCollapsiblePagerTransitionEdgeOwner *> *_programmaticScrollEdges;
|
|
1677
|
+
NSMutableArray<RNCCollapsiblePagerTransitionEdgeOwner *> *_programmaticScrollEdgeOwners;
|
|
1642
1678
|
// OneKey patch: Retain the latest tab tap while an animation is in flight.
|
|
1643
1679
|
NSInteger _pendingGoToIndex;
|
|
1644
1680
|
BOOL _pendingGoToAnimated;
|
|
@@ -1875,11 +1911,14 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1875
1911
|
if (hitView != nil && !sharedHeaderPointIsVisible &&
|
|
1876
1912
|
(hitView == _sharedHeaderHostView ||
|
|
1877
1913
|
[hitView isDescendantOfView:_sharedHeaderHostView])) return nil;
|
|
1878
|
-
if (hitView != nil && _ownedPageMasks.count > 0 &&
|
|
1914
|
+
if (hitView != nil && (_ownedPageMasks.count > 0 || _programmaticScrollEdges.count > 0) &&
|
|
1879
1915
|
[_containerView convertPoint:point fromView:self].y < _pageMaskBoundary) {
|
|
1880
1916
|
for (UIView *page in _ownedPageMasks.keyEnumerator.allObjects) {
|
|
1881
1917
|
if ([hitView isDescendantOfView:page]) return nil;
|
|
1882
1918
|
}
|
|
1919
|
+
for (RNCCollapsiblePagerTransitionEdgeOwner *owner in _programmaticScrollEdges.objectEnumerator) {
|
|
1920
|
+
if (owner.page != nil && [hitView isDescendantOfView:owner.page]) return nil;
|
|
1921
|
+
}
|
|
1883
1922
|
}
|
|
1884
1923
|
return hitView;
|
|
1885
1924
|
}
|
|
@@ -1896,6 +1935,11 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1896
1935
|
- (void)didMoveToWindow
|
|
1897
1936
|
{
|
|
1898
1937
|
[super didMoveToWindow];
|
|
1938
|
+
if (self.window == nil && _pendingNativePagerScrollCompletion != nil) {
|
|
1939
|
+
[self cancelPendingNativePagerScroll];
|
|
1940
|
+
_pagerScrollView.scrollEnabled = _scrollEnabled;
|
|
1941
|
+
[self finishPagerScrollEmittingSelection:NO];
|
|
1942
|
+
}
|
|
1899
1943
|
[self registerExternalOuterPager];
|
|
1900
1944
|
BOOL externalHeightChanged = [self resolveExternalTopOverlay];
|
|
1901
1945
|
if (self.window == nil) [self restoreScrollEdgeContentMasks];
|
|
@@ -1956,6 +2000,9 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1956
2000
|
}
|
|
1957
2001
|
}
|
|
1958
2002
|
if (_externalOuterPager == outer) return;
|
|
2003
|
+
if (_topOverlayView == nil && _externalTopOverlayTag > 0) {
|
|
2004
|
+
[self clearProgrammaticScrollEdges];
|
|
2005
|
+
}
|
|
1959
2006
|
[_externalOuterPager removeNestedOverlayObserver:self];
|
|
1960
2007
|
_externalOuterPager = outer;
|
|
1961
2008
|
_externalOuterPageActive = NO;
|
|
@@ -1987,6 +2034,9 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1987
2034
|
}
|
|
1988
2035
|
BOOL changed = _externalTopOverlayView != nextView ||
|
|
1989
2036
|
fabs(_externalTopOverlayHeight - nextHeight) > 0.5;
|
|
2037
|
+
if (changed && _topOverlayView == nil && _externalTopOverlayTag > 0) {
|
|
2038
|
+
[self clearProgrammaticScrollEdges];
|
|
2039
|
+
}
|
|
1990
2040
|
_externalTopOverlayView = nextView;
|
|
1991
2041
|
_externalTopOverlayHeight = nextHeight;
|
|
1992
2042
|
_topOverlayHostView.hidden = !self.hasFixedTopOverlay;
|
|
@@ -1998,6 +2048,9 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1998
2048
|
{
|
|
1999
2049
|
if (_isBeingRecycled || _externalOuterPager == nil || _externalTopOverlayTag <= 0) return;
|
|
2000
2050
|
if (_externalOuterPageActive == active && _externalOuterTransitioning == transitioning) return;
|
|
2051
|
+
if ((transitioning || !active) && _topOverlayView == nil) {
|
|
2052
|
+
[self clearProgrammaticScrollEdges];
|
|
2053
|
+
}
|
|
2001
2054
|
BOOL wasTransitioning = _externalOuterTransitioning;
|
|
2002
2055
|
_externalOuterPageActive = active;
|
|
2003
2056
|
_externalOuterTransitioning = transitioning;
|
|
@@ -2045,6 +2098,8 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2045
2098
|
|
|
2046
2099
|
- (void)restoreScrollEdgeContentMasks
|
|
2047
2100
|
{
|
|
2101
|
+
[self clearProgrammaticScrollEdges];
|
|
2102
|
+
_programmaticPageMaskIndexes = nil;
|
|
2048
2103
|
if (_sharedHeaderHostView.maskView == _sharedHeaderMaskView) {
|
|
2049
2104
|
_sharedHeaderHostView.maskView = _originalSharedHeaderMaskView;
|
|
2050
2105
|
}
|
|
@@ -2109,11 +2164,14 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2109
2164
|
_pageMaskBoundary = boundary;
|
|
2110
2165
|
NSMutableSet<UIView *> *visiblePages = [NSMutableSet new];
|
|
2111
2166
|
if (transitioning) {
|
|
2112
|
-
for (
|
|
2113
|
-
UIView *page =
|
|
2167
|
+
for (NSUInteger index = 0; index < _pageControllers.count; index++) {
|
|
2168
|
+
UIView *page = _pageControllers[index].view;
|
|
2169
|
+
BOOL programmaticParticipant = [_programmaticPageMaskIndexes containsIndex:index];
|
|
2170
|
+
if ([self hasProgrammaticScrollEdgeForPage:page]) continue;
|
|
2114
2171
|
if (page.window != self.window ||
|
|
2115
|
-
!
|
|
2116
|
-
|
|
2172
|
+
(!programmaticParticipant &&
|
|
2173
|
+
!CGRectIntersectsRect([page convertRect:page.bounds toView:_containerView],
|
|
2174
|
+
_containerView.bounds))) continue;
|
|
2117
2175
|
[visiblePages addObject:page];
|
|
2118
2176
|
UIView *mask = [_ownedPageMasks objectForKey:page];
|
|
2119
2177
|
if (mask == nil) {
|
|
@@ -2125,8 +2183,13 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2125
2183
|
}
|
|
2126
2184
|
CGFloat localTop = [_containerView convertPoint:CGPointMake(0, boundary)
|
|
2127
2185
|
toView:page].y;
|
|
2128
|
-
|
|
2186
|
+
CGRect maskFrame = CGRectMake(0, localTop, CGRectGetWidth(page.bounds),
|
|
2129
2187
|
MAX(0, CGRectGetHeight(page.bounds) - localTop));
|
|
2188
|
+
if (programmaticParticipant) {
|
|
2189
|
+
[UIView performWithoutAnimation:^{ mask.frame = maskFrame; }];
|
|
2190
|
+
} else {
|
|
2191
|
+
mask.frame = maskFrame;
|
|
2192
|
+
}
|
|
2130
2193
|
}
|
|
2131
2194
|
}
|
|
2132
2195
|
for (UIView *page in _ownedPageMasks.keyEnumerator.allObjects) {
|
|
@@ -2253,10 +2316,227 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2253
2316
|
emitter->onScrollEdgeCapability({.available = (bool)available});
|
|
2254
2317
|
}
|
|
2255
2318
|
|
|
2319
|
+
- (RNCCollapsiblePagerTransitionEdgeOwner *)borrowedPinnedStickyOwner
|
|
2320
|
+
{
|
|
2321
|
+
for (RNCCollapsiblePagerTransitionEdgeOwner *owner in _programmaticScrollEdgeOwners) {
|
|
2322
|
+
if (owner.borrowsPinnedStickyHost) return owner;
|
|
2323
|
+
}
|
|
2324
|
+
return nil;
|
|
2325
|
+
}
|
|
2326
|
+
|
|
2327
|
+
- (BOOL)canPreserveHorizontalScrollEdgesAllowExternalOverlay:(BOOL)allowExternalOverlay
|
|
2328
|
+
{
|
|
2329
|
+
if (@available(iOS 27.0, *)) {
|
|
2330
|
+
if (!_directNativePagerEnabled || !_topScrollEdgeEnabled ||
|
|
2331
|
+
!_nativeSmoothHeaderScrollEnabled ||
|
|
2332
|
+
_topScrollEdgeEffect != RNCCollapsiblePagerViewTopScrollEdgeEffect::Hard ||
|
|
2333
|
+
self.window == nil || _isBeingRecycled) return NO;
|
|
2334
|
+
if (_topOverlayView != nil && _externalTopOverlayTag <= 0) return YES;
|
|
2335
|
+
return allowExternalOverlay && _topOverlayView == nil && _externalTopOverlayTag > 0 &&
|
|
2336
|
+
_externalTopOverlayView.window == self.window && _externalTopOverlayHeight > 0 &&
|
|
2337
|
+
_topOverlayHostView.window == self.window && !_topOverlayHostView.hidden &&
|
|
2338
|
+
(_externalOuterPager == nil || (_externalOuterPageActive && !_externalOuterTransitioning));
|
|
2339
|
+
}
|
|
2340
|
+
return NO;
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
- (void)adoptCurrentScrollEdgeForProgrammaticTransition:(BOOL)allowExternalOverlay
|
|
2344
|
+
{
|
|
2345
|
+
if (@available(iOS 27.0, *)) {
|
|
2346
|
+
UIScrollView *source = _observedScrollView;
|
|
2347
|
+
if (![self canPreserveHorizontalScrollEdgesAllowExternalOverlay:allowExternalOverlay] ||
|
|
2348
|
+
source == nil || source != _topEdgeScrollView ||
|
|
2349
|
+
_topEdgeInteraction == nil || _topEdgeInteraction.scrollView != source ||
|
|
2350
|
+
_currentIndex < 0 || _currentIndex >= _pageControllers.count) return;
|
|
2351
|
+
|
|
2352
|
+
RNCCollapsiblePagerTransitionEdgeOwner *existing =
|
|
2353
|
+
[_programmaticScrollEdges objectForKey:source];
|
|
2354
|
+
if (existing != nil && existing.topInteraction.scrollView == source) return;
|
|
2355
|
+
if (existing != nil) [self releaseProgrammaticScrollEdgeOwner:existing];
|
|
2356
|
+
if (_programmaticScrollEdges == nil) {
|
|
2357
|
+
_programmaticScrollEdges = [NSMapTable weakToStrongObjectsMapTable];
|
|
2358
|
+
_programmaticScrollEdgeOwners = [NSMutableArray new];
|
|
2359
|
+
}
|
|
2360
|
+
RNCCollapsiblePagerTransitionEdgeOwner *owner = [RNCCollapsiblePagerTransitionEdgeOwner new];
|
|
2361
|
+
owner.scrollView = source;
|
|
2362
|
+
owner.page = _pageControllers[_currentIndex].view;
|
|
2363
|
+
owner.originalStyle = _originalTopEdgeStyle;
|
|
2364
|
+
owner.topInteraction = _topEdgeInteraction;
|
|
2365
|
+
owner.topHost = _topEdgeInteractionHost;
|
|
2366
|
+
owner.topMarker = _topEdgeMarker;
|
|
2367
|
+
owner.stickyInteraction = _stickyEdgeInteraction;
|
|
2368
|
+
owner.stickyHost = _stickyEdgeInteractionHost;
|
|
2369
|
+
owner.stickyMarker = _stickyEdgeMarker;
|
|
2370
|
+
owner.borrowsPinnedStickyHost = _stickyHeaderIsPinned &&
|
|
2371
|
+
owner.stickyHost == _pinnedStickyHostView &&
|
|
2372
|
+
owner.stickyInteraction.scrollView == source;
|
|
2373
|
+
[_programmaticScrollEdges setObject:owner forKey:source];
|
|
2374
|
+
[_programmaticScrollEdgeOwners addObject:owner];
|
|
2375
|
+
|
|
2376
|
+
// Transfer ownership without detaching UIKit's existing edge resources.
|
|
2377
|
+
_topEdgeInteraction = nil;
|
|
2378
|
+
_stickyEdgeInteraction = nil;
|
|
2379
|
+
_topEdgeMarker = nil;
|
|
2380
|
+
_stickyEdgeMarker = nil;
|
|
2381
|
+
_topEdgeInteractionHost = nil;
|
|
2382
|
+
_stickyEdgeInteractionHost = nil;
|
|
2383
|
+
_topEdgeScrollView = nil;
|
|
2384
|
+
_originalTopEdgeStyle = nil;
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
- (void)beginProgrammaticScrollEdgesToIndex:(NSInteger)index allowExternalOverlay:(BOOL)allowExternalOverlay
|
|
2389
|
+
{
|
|
2390
|
+
if (@available(iOS 27.0, *)) {
|
|
2391
|
+
if (![self canPreserveHorizontalScrollEdgesAllowExternalOverlay:allowExternalOverlay]) return;
|
|
2392
|
+
if (_programmaticScrollEdges == nil) {
|
|
2393
|
+
_programmaticScrollEdges = [NSMapTable weakToStrongObjectsMapTable];
|
|
2394
|
+
_programmaticScrollEdgeOwners = [NSMutableArray new];
|
|
2395
|
+
}
|
|
2396
|
+
NSInteger first = MIN(_currentIndex, index);
|
|
2397
|
+
NSInteger last = MAX(_currentIndex, index);
|
|
2398
|
+
for (NSInteger pageIndex = first; pageIndex <= last; pageIndex++) {
|
|
2399
|
+
[self preparePageForHorizontalTransitionAtIndex:pageIndex];
|
|
2400
|
+
UIScrollView *scrollView = [self verticalScrollViewForPageAtIndex:pageIndex];
|
|
2401
|
+
if (scrollView == nil || scrollView.window != self.window) continue;
|
|
2402
|
+
if ([_programmaticScrollEdges objectForKey:scrollView] != nil) continue;
|
|
2403
|
+
RNCCollapsiblePagerTransitionEdgeOwner *owner = [RNCCollapsiblePagerTransitionEdgeOwner new];
|
|
2404
|
+
owner.scrollView = scrollView;
|
|
2405
|
+
owner.page = _pageControllers[pageIndex].view;
|
|
2406
|
+
owner.originalStyle = scrollView.topEdgeEffect.style;
|
|
2407
|
+
scrollView.topEdgeEffect.style = UIScrollEdgeEffectStyle.hardStyle;
|
|
2408
|
+
UILabel *(^markerForHost)(UIView *) = ^UILabel *(UIView *host) {
|
|
2409
|
+
UILabel *marker = [UILabel new];
|
|
2410
|
+
marker.frame = host.bounds;
|
|
2411
|
+
marker.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
2412
|
+
marker.text = @" ";
|
|
2413
|
+
marker.textColor = UIColor.clearColor;
|
|
2414
|
+
marker.backgroundColor = UIColor.clearColor;
|
|
2415
|
+
marker.userInteractionEnabled = NO;
|
|
2416
|
+
marker.isAccessibilityElement = NO;
|
|
2417
|
+
marker.accessibilityElementsHidden = YES;
|
|
2418
|
+
[host addSubview:marker];
|
|
2419
|
+
return marker;
|
|
2420
|
+
};
|
|
2421
|
+
owner.ownsTransitionHosts = allowExternalOverlay && _topOverlayView == nil &&
|
|
2422
|
+
_externalTopOverlayTag > 0 && pageIndex != _currentIndex;
|
|
2423
|
+
UIView *(^transitionHost)(UIView *) = ^UIView *(UIView *referenceHost) {
|
|
2424
|
+
CGRect frame = [referenceHost convertRect:referenceHost.bounds toView:owner.page];
|
|
2425
|
+
CGRect viewport = [scrollView convertRect:scrollView.bounds toView:owner.page];
|
|
2426
|
+
frame.origin.x = CGRectGetMinX(viewport);
|
|
2427
|
+
UIView *host = [[UIView alloc] initWithFrame:frame];
|
|
2428
|
+
host.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
|
2429
|
+
host.userInteractionEnabled = NO;
|
|
2430
|
+
host.accessibilityElementsHidden = YES;
|
|
2431
|
+
[owner.page addSubview:host];
|
|
2432
|
+
return host;
|
|
2433
|
+
};
|
|
2434
|
+
if (owner.ownsTransitionHosts) {
|
|
2435
|
+
owner.ownedTopHost = transitionHost(_topOverlayHostView);
|
|
2436
|
+
owner.topHost = owner.ownedTopHost;
|
|
2437
|
+
} else {
|
|
2438
|
+
owner.topHost = _topOverlayHostView;
|
|
2439
|
+
}
|
|
2440
|
+
owner.topMarker = markerForHost(owner.topHost);
|
|
2441
|
+
owner.topInteraction = [UIScrollEdgeElementContainerInteraction new];
|
|
2442
|
+
owner.topInteraction.edge = UIRectEdgeTop;
|
|
2443
|
+
owner.topInteraction.scrollView = scrollView;
|
|
2444
|
+
[owner.topHost addInteraction:owner.topInteraction];
|
|
2445
|
+
if (_stickyHeaderView != nil && _headerOffset >= _headerHeight - 0.5) {
|
|
2446
|
+
if (owner.ownsTransitionHosts) {
|
|
2447
|
+
owner.ownedStickyHost = transitionHost(_stickyHeaderView);
|
|
2448
|
+
owner.stickyHost = owner.ownedStickyHost;
|
|
2449
|
+
} else {
|
|
2450
|
+
owner.stickyHost = _stickyHeaderView;
|
|
2451
|
+
}
|
|
2452
|
+
owner.stickyMarker = markerForHost(owner.stickyHost);
|
|
2453
|
+
owner.stickyInteraction = [UIScrollEdgeElementContainerInteraction new];
|
|
2454
|
+
owner.stickyInteraction.edge = UIRectEdgeTop;
|
|
2455
|
+
owner.stickyInteraction.scrollView = scrollView;
|
|
2456
|
+
[owner.stickyHost addInteraction:owner.stickyInteraction];
|
|
2457
|
+
}
|
|
2458
|
+
[_programmaticScrollEdges setObject:owner forKey:scrollView];
|
|
2459
|
+
[_programmaticScrollEdgeOwners addObject:owner];
|
|
2460
|
+
}
|
|
2461
|
+
[self updateScrollEdgeContentMasks];
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
- (void)releaseProgrammaticScrollEdge:(UIScrollView *)scrollView
|
|
2466
|
+
{
|
|
2467
|
+
if (scrollView == nil) return;
|
|
2468
|
+
[self releaseProgrammaticScrollEdgeOwner:[_programmaticScrollEdges objectForKey:scrollView]];
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
- (void)releaseProgrammaticScrollEdgeOwner:(RNCCollapsiblePagerTransitionEdgeOwner *)owner
|
|
2472
|
+
{
|
|
2473
|
+
if (@available(iOS 26.0, *)) {
|
|
2474
|
+
if (owner == nil) return;
|
|
2475
|
+
UIScrollView *scrollView = owner.scrollView;
|
|
2476
|
+
[owner.topHost removeInteraction:owner.topInteraction];
|
|
2477
|
+
owner.topInteraction.scrollView = nil;
|
|
2478
|
+
[owner.stickyHost removeInteraction:owner.stickyInteraction];
|
|
2479
|
+
owner.stickyInteraction.scrollView = nil;
|
|
2480
|
+
[owner.topMarker removeFromSuperview];
|
|
2481
|
+
[owner.stickyMarker removeFromSuperview];
|
|
2482
|
+
if (owner.ownsTransitionHosts) {
|
|
2483
|
+
[owner.ownedTopHost removeFromSuperview];
|
|
2484
|
+
[owner.ownedStickyHost removeFromSuperview];
|
|
2485
|
+
owner.ownedTopHost = nil;
|
|
2486
|
+
owner.ownedStickyHost = nil;
|
|
2487
|
+
}
|
|
2488
|
+
scrollView.topEdgeEffect.style = owner.originalStyle;
|
|
2489
|
+
if (owner.borrowsPinnedStickyHost && !_stickyHeaderIsPinned &&
|
|
2490
|
+
(_pinnedStickyHostView.superview == scrollView ||
|
|
2491
|
+
_pinnedStickyHostView.superview == nil)) {
|
|
2492
|
+
_pinnedStickyHostView.hidden = YES;
|
|
2493
|
+
_pinnedStickyHostView.layer.zPosition = 0;
|
|
2494
|
+
[_containerView addSubview:_pinnedStickyHostView];
|
|
2495
|
+
}
|
|
2496
|
+
if (scrollView != nil) [_programmaticScrollEdges removeObjectForKey:scrollView];
|
|
2497
|
+
[_programmaticScrollEdgeOwners removeObjectIdenticalTo:owner];
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
- (void)clearProgrammaticScrollEdges
|
|
2502
|
+
{
|
|
2503
|
+
for (RNCCollapsiblePagerTransitionEdgeOwner *owner in _programmaticScrollEdgeOwners.copy) {
|
|
2504
|
+
[self releaseProgrammaticScrollEdgeOwner:owner];
|
|
2505
|
+
}
|
|
2506
|
+
_programmaticScrollEdges = nil;
|
|
2507
|
+
_programmaticScrollEdgeOwners = nil;
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
- (void)finishProgrammaticScrollEdges
|
|
2511
|
+
{
|
|
2512
|
+
if (_programmaticScrollEdgeOwners.count == 0) return;
|
|
2513
|
+
[self clearProgrammaticScrollEdges];
|
|
2514
|
+
[self updateTopScrollEdgeForScrollView:_observedScrollView];
|
|
2515
|
+
}
|
|
2516
|
+
|
|
2517
|
+
- (BOOL)hasProgrammaticScrollEdgeForPage:(UIView *)page
|
|
2518
|
+
{
|
|
2519
|
+
if (@available(iOS 26.0, *)) {
|
|
2520
|
+
for (RNCCollapsiblePagerTransitionEdgeOwner *owner in _programmaticScrollEdges.objectEnumerator) {
|
|
2521
|
+
if (owner.page == page && owner.scrollView.window == self.window &&
|
|
2522
|
+
owner.topInteraction.scrollView == owner.scrollView) return YES;
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
return NO;
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2256
2528
|
- (void)updateTopScrollEdgeForScrollView:(UIScrollView *)scrollView
|
|
2257
2529
|
{
|
|
2258
2530
|
[self syncScrollEdgeAppearance];
|
|
2259
2531
|
if (@available(iOS 26.0, *)) {
|
|
2532
|
+
if (_programmaticScrollEdgeOwners.count > 0 &&
|
|
2533
|
+
![self canPreserveHorizontalScrollEdgesAllowExternalOverlay:YES]) {
|
|
2534
|
+
[self clearProgrammaticScrollEdges];
|
|
2535
|
+
}
|
|
2536
|
+
if (scrollView != nil && [_programmaticScrollEdges objectForKey:scrollView] != nil) {
|
|
2537
|
+
[self updateScrollEdgeContentMasks];
|
|
2538
|
+
return;
|
|
2539
|
+
}
|
|
2260
2540
|
if (_pendingTopOverlayAppearanceCommit) scrollView = nil;
|
|
2261
2541
|
BOOL externalOwnerReady = _externalTopOverlayTag <= 0 ||
|
|
2262
2542
|
_externalOuterPager == nil ||
|
|
@@ -2400,6 +2680,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2400
2680
|
|
|
2401
2681
|
- (void)dealloc
|
|
2402
2682
|
{
|
|
2683
|
+
[self clearProgrammaticScrollEdges];
|
|
2403
2684
|
[self updateTopScrollEdgeForScrollView:nil];
|
|
2404
2685
|
[self cancelHeaderSettledCheck];
|
|
2405
2686
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"OneKeyNativeListScrollCommandAccepted" object:nil];
|
|
@@ -2453,6 +2734,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2453
2734
|
}
|
|
2454
2735
|
_hasPendingDirectNativePagerChange = NO;
|
|
2455
2736
|
if (_directNativePagerEnabled == enabled) return;
|
|
2737
|
+
[self cancelPendingNativePagerScroll];
|
|
2456
2738
|
|
|
2457
2739
|
[self restoreScrollEdgeContentMasks];
|
|
2458
2740
|
[self detachScrollObserver];
|
|
@@ -2533,6 +2815,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2533
2815
|
- (void)restorePinnedStickyHeader
|
|
2534
2816
|
{
|
|
2535
2817
|
if (!_stickyHeaderIsPinned) return;
|
|
2818
|
+
BOOL borrowedHost = [self borrowedPinnedStickyOwner] != nil;
|
|
2536
2819
|
_stickyHeaderIsPinned = NO;
|
|
2537
2820
|
_stickyHeaderView.transform = CGAffineTransformIdentity;
|
|
2538
2821
|
_nativeTabBarView.transform = CGAffineTransformIdentity;
|
|
@@ -2543,9 +2826,11 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2543
2826
|
if (_stickyHeaderView != nil) [_sharedHeaderHostView addSubview:_stickyHeaderView];
|
|
2544
2827
|
[_sharedHeaderHostView addSubview:_nativeTabBarView];
|
|
2545
2828
|
[_sharedHeaderHostView addSubview:_nativeSubHeaderView];
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2829
|
+
if (!borrowedHost) {
|
|
2830
|
+
_pinnedStickyHostView.hidden = YES;
|
|
2831
|
+
_pinnedStickyHostView.layer.zPosition = 0;
|
|
2832
|
+
[_containerView addSubview:_pinnedStickyHostView];
|
|
2833
|
+
}
|
|
2549
2834
|
if ([_pagerScrollView isKindOfClass:RNCCollapsiblePagerDirectScrollView.class]) {
|
|
2550
2835
|
((RNCCollapsiblePagerDirectScrollView *)_pagerScrollView).excludedHeaderView = _sharedHeaderHostView;
|
|
2551
2836
|
}
|
|
@@ -2647,8 +2932,11 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2647
2932
|
);
|
|
2648
2933
|
CGFloat stickyY = _headerHeight;
|
|
2649
2934
|
_headerView.frame = CGRectMake(0, 0, width, _headerHeight);
|
|
2650
|
-
|
|
2651
|
-
|
|
2935
|
+
RNCCollapsiblePagerTransitionEdgeOwner *borrowedOwner = [self borrowedPinnedStickyOwner];
|
|
2936
|
+
UIScrollView *pinnedScrollView = borrowedOwner.scrollView ?: _sharedHeaderScrollView;
|
|
2937
|
+
CGPoint pinnedOrigin = (borrowedOwner != nil || _stickyHeaderIsPinned) && pinnedScrollView != nil
|
|
2938
|
+
? [pinnedScrollView convertPoint:CGPointMake(0, self.effectiveTopOverlayHeight)
|
|
2939
|
+
fromView:_containerView]
|
|
2652
2940
|
: CGPointMake(0, self.effectiveTopOverlayHeight);
|
|
2653
2941
|
_pinnedStickyHostView.frame = CGRectMake(
|
|
2654
2942
|
pinnedOrigin.x, pinnedOrigin.y, width, _stickyHeaderHeight);
|
|
@@ -3083,6 +3371,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3083
3371
|
}
|
|
3084
3372
|
_needsSlotRebuild = NO;
|
|
3085
3373
|
_deferTopEdgeSlotRebuild = NO;
|
|
3374
|
+
[self cancelPendingNativePagerScroll];
|
|
3086
3375
|
[self restoreScrollEdgeContentMasks];
|
|
3087
3376
|
[self detachScrollObserver];
|
|
3088
3377
|
[self restoreSharedHeadersToContainer];
|
|
@@ -3173,6 +3462,19 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3173
3462
|
- (void)layoutSubviews
|
|
3174
3463
|
{
|
|
3175
3464
|
[super layoutSubviews];
|
|
3465
|
+
void (^resizedPagerCompletion)(BOOL) = nil;
|
|
3466
|
+
NSInteger resizedPagerDestination = -1;
|
|
3467
|
+
NSUInteger resizedPagerGeneration = 0;
|
|
3468
|
+
NSUInteger resizedPagerTransition = 0;
|
|
3469
|
+
if (_directNativePagerEnabled && _pendingNativePagerScrollCompletion != nil &&
|
|
3470
|
+
CGRectGetWidth(_pagerScrollView.bounds) != CGRectGetWidth(self.bounds)) {
|
|
3471
|
+
resizedPagerCompletion = [_pendingNativePagerScrollCompletion copy];
|
|
3472
|
+
resizedPagerDestination = _destinationIndex;
|
|
3473
|
+
resizedPagerGeneration = _pendingNativePagerScrollGeneration;
|
|
3474
|
+
resizedPagerTransition = _pendingNativePagerScrollTransition;
|
|
3475
|
+
// Clear the old target before frame changes can deliver an animation end.
|
|
3476
|
+
[self cancelPendingNativePagerScroll];
|
|
3477
|
+
}
|
|
3176
3478
|
[self syncScrollEdgeAppearance];
|
|
3177
3479
|
_containerView.frame = self.bounds;
|
|
3178
3480
|
[self registerExternalOuterPager];
|
|
@@ -3245,10 +3547,20 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3245
3547
|
[self updateHeaderSettledStateForceBusy:NO];
|
|
3246
3548
|
[self logHomeVisualGeometry:@"layout" scrollView:_observedScrollView];
|
|
3247
3549
|
[self scheduleCoalescedScrollReconcile];
|
|
3550
|
+
if (resizedPagerCompletion != nil && _directNativePagerEnabled &&
|
|
3551
|
+
!_isBeingRecycled && !_isPagerDragging && _generation == resizedPagerGeneration &&
|
|
3552
|
+
_transitionId == resizedPagerTransition && resizedPagerDestination >= 0 &&
|
|
3553
|
+
resizedPagerDestination < _pageControllers.count) {
|
|
3554
|
+
[_pagerScrollView setContentOffset:CGPointMake(
|
|
3555
|
+
[self directPagerOffsetForIndex:resizedPagerDestination], 0
|
|
3556
|
+
) animated:NO];
|
|
3557
|
+
resizedPagerCompletion(YES);
|
|
3558
|
+
}
|
|
3248
3559
|
}
|
|
3249
3560
|
|
|
3250
3561
|
- (void)prepareForRecycle
|
|
3251
3562
|
{
|
|
3563
|
+
[self cancelPendingNativePagerScroll];
|
|
3252
3564
|
[_externalOuterPager removeNestedOverlayObserver:self];
|
|
3253
3565
|
_externalOuterPager = nil;
|
|
3254
3566
|
[self cancelTopInsetReboundCheck];
|
|
@@ -3501,6 +3813,10 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3501
3813
|
}
|
|
3502
3814
|
if (_needsPropsReapply ||
|
|
3503
3815
|
oldViewProps.externalTopOverlayTag != newViewProps.externalTopOverlayTag) {
|
|
3816
|
+
if (_topOverlayView == nil && _externalTopOverlayTag > 0 &&
|
|
3817
|
+
_externalTopOverlayTag != newViewProps.externalTopOverlayTag) {
|
|
3818
|
+
[self clearProgrammaticScrollEdges];
|
|
3819
|
+
}
|
|
3504
3820
|
_externalTopOverlayTag = newViewProps.externalTopOverlayTag;
|
|
3505
3821
|
[self registerExternalOuterPager];
|
|
3506
3822
|
insetsChanged = [self resolveExternalTopOverlay] || insetsChanged;
|
|
@@ -4439,6 +4755,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
4439
4755
|
// still represents the old list, before Fabric applies its next owner's props.
|
|
4440
4756
|
- (void)restoreScrollViewState:(UIScrollView *)scrollView resetSavedOffset:(BOOL)resetSavedOffset
|
|
4441
4757
|
{
|
|
4758
|
+
[self releaseProgrammaticScrollEdge:scrollView];
|
|
4442
4759
|
[self updateNativeScrollerViewport:scrollView stickyHeight:0];
|
|
4443
4760
|
[self releaseRefreshControlForScrollView:scrollView];
|
|
4444
4761
|
if (scrollView == _observedScrollView) {
|
|
@@ -5005,6 +5322,17 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
5005
5322
|
|
|
5006
5323
|
#pragma mark - Pager navigation
|
|
5007
5324
|
|
|
5325
|
+
- (void)cancelPendingNativePagerScroll
|
|
5326
|
+
{
|
|
5327
|
+
if (_pendingNativePagerScrollCompletion == nil) return;
|
|
5328
|
+
_pendingNativePagerScrollCompletion = nil;
|
|
5329
|
+
_pendingNativePagerScrollGeneration = 0;
|
|
5330
|
+
_pendingNativePagerScrollTransition = 0;
|
|
5331
|
+
_pendingNativePagerScrollTarget = 0;
|
|
5332
|
+
CGPoint offset = _pagerScrollView.contentOffset;
|
|
5333
|
+
[_pagerScrollView setContentOffset:offset animated:NO];
|
|
5334
|
+
}
|
|
5335
|
+
|
|
5008
5336
|
- (BOOL)isLtrLayout
|
|
5009
5337
|
{
|
|
5010
5338
|
return [_layoutDirection isEqualToString:@"ltr"];
|
|
@@ -5038,11 +5366,17 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
5038
5366
|
return;
|
|
5039
5367
|
}
|
|
5040
5368
|
|
|
5369
|
+
if (_directNativePagerEnabled && animated && index != _currentIndex) {
|
|
5370
|
+
[self adoptCurrentScrollEdgeForProgrammaticTransition:NO];
|
|
5371
|
+
}
|
|
5041
5372
|
[self beginPageStateTransition];
|
|
5042
5373
|
[self preparePageForHorizontalTransitionAtIndex:index];
|
|
5043
5374
|
_destinationIndex = index;
|
|
5044
5375
|
[self liftSharedHeadersForPagerTransition:@"programmatic"];
|
|
5045
5376
|
[self detachScrollObserver];
|
|
5377
|
+
if (_directNativePagerEnabled && animated && index != _currentIndex) {
|
|
5378
|
+
[self beginProgrammaticScrollEdgesToIndex:index allowExternalOverlay:NO];
|
|
5379
|
+
}
|
|
5046
5380
|
BOOL forward = (index > _currentIndex && self.isLtrLayout) ||
|
|
5047
5381
|
(index < _currentIndex && !self.isLtrLayout);
|
|
5048
5382
|
UIPageViewControllerNavigationDirection direction = forward
|
|
@@ -5082,13 +5416,41 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
5082
5416
|
};
|
|
5083
5417
|
|
|
5084
5418
|
if (animated && index != _currentIndex) {
|
|
5419
|
+
BOOL useNativeAnimatedScroll = NO;
|
|
5420
|
+
if (@available(iOS 27.0, *)) {
|
|
5421
|
+
useNativeAnimatedScroll = _nativeSmoothHeaderScrollEnabled && _topScrollEdgeEnabled &&
|
|
5422
|
+
_topScrollEdgeEffect == RNCCollapsiblePagerViewTopScrollEdgeEffect::Hard &&
|
|
5423
|
+
_topOverlayView != nil && _externalTopOverlayTag <= 0 && self.window != nil;
|
|
5424
|
+
}
|
|
5425
|
+
if (useNativeAnimatedScroll) {
|
|
5426
|
+
// Keep the traversed pages owned until UIKit finishes scrolling.
|
|
5427
|
+
NSInteger first = MIN(_currentIndex, index);
|
|
5428
|
+
NSInteger last = MAX(_currentIndex, index);
|
|
5429
|
+
_programmaticPageMaskIndexes = [NSIndexSet indexSetWithIndexesInRange:
|
|
5430
|
+
NSMakeRange(first, last - first + 1)];
|
|
5431
|
+
[self updateScrollEdgeContentMasks];
|
|
5432
|
+
}
|
|
5085
5433
|
_pagerScrollView.scrollEnabled = NO;
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5434
|
+
if (useNativeAnimatedScroll) {
|
|
5435
|
+
if (fabs(_pagerScrollView.contentOffset.x - targetOffset) <= 0.5) {
|
|
5436
|
+
[_nativeTabBarView setProgress:index];
|
|
5437
|
+
[self updatePageStateTransitionProgress:index];
|
|
5438
|
+
completion(YES);
|
|
5439
|
+
} else {
|
|
5440
|
+
_pendingNativePagerScrollCompletion = [completion copy];
|
|
5441
|
+
_pendingNativePagerScrollGeneration = capturedGeneration;
|
|
5442
|
+
_pendingNativePagerScrollTransition = capturedTransition;
|
|
5443
|
+
_pendingNativePagerScrollTarget = targetOffset;
|
|
5444
|
+
[_pagerScrollView setContentOffset:CGPointMake(targetOffset, 0) animated:YES];
|
|
5445
|
+
}
|
|
5446
|
+
} else {
|
|
5447
|
+
[UIView animateWithDuration:0.28
|
|
5448
|
+
delay:0
|
|
5449
|
+
options:UIViewAnimationOptionCurveEaseInOut |
|
|
5450
|
+
UIViewAnimationOptionAllowUserInteraction
|
|
5451
|
+
animations:animations
|
|
5452
|
+
completion:completion];
|
|
5453
|
+
}
|
|
5092
5454
|
} else {
|
|
5093
5455
|
[UIView performWithoutAnimation:animations];
|
|
5094
5456
|
completion(YES);
|
|
@@ -5130,7 +5492,10 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
5130
5492
|
if (self->_generation != generation || self->_transitionId != transition ||
|
|
5131
5493
|
self->_isBeingRecycled) return;
|
|
5132
5494
|
[self finishPageStateTransition];
|
|
5495
|
+
self->_programmaticPageMaskIndexes = nil;
|
|
5133
5496
|
self->_transitioning = NO;
|
|
5497
|
+
BOOL hadProgrammaticScrollEdges = self->_programmaticScrollEdgeOwners.count > 0;
|
|
5498
|
+
[self finishProgrammaticScrollEdges];
|
|
5134
5499
|
if (self->_hasPendingDirectNativePagerChange) {
|
|
5135
5500
|
BOOL enabled = self->_pendingDirectNativePagerEnabled;
|
|
5136
5501
|
self->_hasPendingDirectNativePagerChange = NO;
|
|
@@ -5139,8 +5504,11 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
5139
5504
|
[self rebuildSlots];
|
|
5140
5505
|
}
|
|
5141
5506
|
if (!self->_hasAppliedInitialPage) [self setNeedsLayout];
|
|
5507
|
+
if (hadProgrammaticScrollEdges && !self->_transitioning && !self->_needsSlotRebuild) {
|
|
5508
|
+
[self attachScrollObserverForCurrentPage];
|
|
5509
|
+
}
|
|
5142
5510
|
[self drainPendingGoTo];
|
|
5143
|
-
if (!self->_transitioning && !self->_needsSlotRebuild) {
|
|
5511
|
+
if (!hadProgrammaticScrollEdges && !self->_transitioning && !self->_needsSlotRebuild) {
|
|
5144
5512
|
[self attachScrollObserverForCurrentPage];
|
|
5145
5513
|
}
|
|
5146
5514
|
[self updateScrollEdgeContentMasks];
|
|
@@ -5194,21 +5562,30 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
5194
5562
|
|
|
5195
5563
|
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
|
|
5196
5564
|
{
|
|
5565
|
+
if (scrollView == _pagerScrollView) [self cancelPendingNativePagerScroll];
|
|
5566
|
+
++_transitionId;
|
|
5197
5567
|
[self updateHeaderSettledStateForceBusy:YES];
|
|
5198
5568
|
if (_nativeSmoothHeaderScrollEnabled && scrollView == _pagerScrollView) {
|
|
5199
5569
|
[_contentPressCancellationGesture cancelPressForPan:scrollView.panGestureRecognizer];
|
|
5200
5570
|
}
|
|
5571
|
+
if (_directNativePagerEnabled) [self adoptCurrentScrollEdgeForProgrammaticTransition:YES];
|
|
5201
5572
|
[self beginPageStateTransition];
|
|
5202
5573
|
if (_directNativePagerEnabled) {
|
|
5203
5574
|
[self preparePageForHorizontalTransitionAtIndex:_currentIndex - 1];
|
|
5204
5575
|
[self preparePageForHorizontalTransitionAtIndex:_currentIndex + 1];
|
|
5205
5576
|
}
|
|
5206
5577
|
// A user drag owns the result even if UIKit later completes the old animation.
|
|
5207
|
-
|
|
5578
|
+
_programmaticPageMaskIndexes = nil;
|
|
5208
5579
|
[self liftSharedHeadersForPagerTransition:@"interactive"];
|
|
5209
5580
|
[self detachScrollObserver];
|
|
5210
5581
|
_isPagerDragging = YES;
|
|
5211
5582
|
_transitioning = YES;
|
|
5583
|
+
if (_directNativePagerEnabled) {
|
|
5584
|
+
if (_currentIndex > 0) [self beginProgrammaticScrollEdgesToIndex:_currentIndex - 1 allowExternalOverlay:YES];
|
|
5585
|
+
if (_currentIndex + 1 < _pageControllers.count) {
|
|
5586
|
+
[self beginProgrammaticScrollEdgesToIndex:_currentIndex + 1 allowExternalOverlay:YES];
|
|
5587
|
+
}
|
|
5588
|
+
}
|
|
5212
5589
|
if (_nativeSmoothHeaderScrollEnabled) {
|
|
5213
5590
|
RNCCollapsiblePagerLog([NSString stringWithFormat:
|
|
5214
5591
|
@"gesture-owner=pager page=%ld",
|
|
@@ -5341,6 +5718,20 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
5341
5718
|
[self finishPagerScrollEmittingSelection:YES];
|
|
5342
5719
|
}
|
|
5343
5720
|
|
|
5721
|
+
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
|
|
5722
|
+
{
|
|
5723
|
+
if (scrollView != _pagerScrollView || _pendingNativePagerScrollCompletion == nil ||
|
|
5724
|
+
scrollView.isDragging || _generation != _pendingNativePagerScrollGeneration ||
|
|
5725
|
+
_transitionId != _pendingNativePagerScrollTransition ||
|
|
5726
|
+
fabs(scrollView.contentOffset.x - _pendingNativePagerScrollTarget) > 0.5) return;
|
|
5727
|
+
void (^completion)(BOOL) = _pendingNativePagerScrollCompletion;
|
|
5728
|
+
_pendingNativePagerScrollCompletion = nil;
|
|
5729
|
+
_pendingNativePagerScrollGeneration = 0;
|
|
5730
|
+
_pendingNativePagerScrollTransition = 0;
|
|
5731
|
+
_pendingNativePagerScrollTarget = 0;
|
|
5732
|
+
completion(YES);
|
|
5733
|
+
}
|
|
5734
|
+
|
|
5344
5735
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
|
5345
5736
|
{
|
|
5346
5737
|
CGFloat width = scrollView.bounds.size.width;
|