@onekeyfe/react-native-pager-view 3.0.172 → 3.0.174
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/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +506 -56
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +4 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerView.kt +14 -0
- package/android/src/main/res/values/native_scroll_coordinator_ids.xml +2 -0
- package/docs/SPEC.md +54 -48
- package/ios/RNCCollapsiblePagerViewComponentView.mm +245 -32
- package/ios/RNCNativeScrollerComponentView.mm +6 -0
- package/ios/tests/RNCCollapsiblePagerFirstFrameTests.mm +85 -49
- package/ios/tests/RNCCollapsiblePagerRefreshControlTests.mm +14 -5
- package/lib/module/CollapsiblePagerView.js +6 -0
- package/lib/module/CollapsiblePagerView.web.js +81 -0
- package/lib/module/CollapsiblePagerViewNativeComponent.ts +6 -0
- package/lib/typescript/src/CollapsiblePagerView.d.ts +6 -0
- package/lib/typescript/src/CollapsiblePagerView.web.d.ts +11 -0
- package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +1 -0
- package/package.json +2 -2
- package/src/CollapsiblePagerView.tsx +18 -0
- package/src/CollapsiblePagerView.web.tsx +170 -36
- package/src/CollapsiblePagerViewNativeComponent.ts +6 -0
|
@@ -324,6 +324,10 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
|
|
|
324
324
|
delegate.receiveCommand(root, commandId, args)
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
+
override fun scrollToTop(view: CollapsiblePagerHost?, target: Int, animated: Boolean) {
|
|
328
|
+
view?.scrollToTop(target, animated)
|
|
329
|
+
}
|
|
330
|
+
|
|
327
331
|
override fun setPage(view: CollapsiblePagerHost?, selectedPage: Int) {
|
|
328
332
|
if (view != null && selectedPage in 0 until view.adapter.itemCount) {
|
|
329
333
|
view.beginPageTransition(selectedPage)
|
|
@@ -295,11 +295,22 @@ class NativeScrollerView(context: Context) : FrameLayout(context) {
|
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
internal fun scrollToPosition(x: Int, y: Int, animated: Boolean) {
|
|
298
|
+
notifyScrollCommand(0, y <= 0)
|
|
298
299
|
viewport.stopMotion()
|
|
299
300
|
pendingRestore.cancel()
|
|
301
|
+
notifyScrollCommand(1, y <= 0)
|
|
300
302
|
if (animated) viewport.scrollToAnimated(y)
|
|
301
303
|
else viewport.scrollTo(0, y.coerceAtLeast(0))
|
|
302
304
|
emitScroll(force = true)
|
|
305
|
+
if (!viewport.isReadingMotionActive()) notifyScrollCommand(2, y <= 0)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
internal fun notifyScrollCommand(phase: Int, explicitTop: Boolean = false) {
|
|
309
|
+
var owner = parent
|
|
310
|
+
while (owner is View) {
|
|
311
|
+
if (owner is CollapsiblePagerHost) owner.acceptObservedScrollCommand(viewport, explicitTop, phase)
|
|
312
|
+
owner = owner.parent
|
|
313
|
+
}
|
|
303
314
|
}
|
|
304
315
|
|
|
305
316
|
internal fun scrollToEnd(animated: Boolean) = scrollToPosition(
|
|
@@ -589,6 +600,8 @@ internal class NativeScrollerViewport(context: Context, internal val host: Nativ
|
|
|
589
600
|
super.fling(velocityY)
|
|
590
601
|
}
|
|
591
602
|
|
|
603
|
+
internal fun isReadingMotionActive() = dragging || momentum
|
|
604
|
+
|
|
592
605
|
internal fun scrollToAnimated(y: Int) {
|
|
593
606
|
val child = getChildAt(0) ?: return
|
|
594
607
|
val margins = child.layoutParams as FrameLayout.LayoutParams
|
|
@@ -639,6 +652,7 @@ internal class NativeScrollerViewport(context: Context, internal val host: Nativ
|
|
|
639
652
|
private fun finishMomentum() {
|
|
640
653
|
if (!momentum) return
|
|
641
654
|
momentum = false
|
|
655
|
+
host.notifyScrollCommand(2)
|
|
642
656
|
host.emitScroll(force = true)
|
|
643
657
|
host.emitLifecycle("topMomentumScrollEnd")
|
|
644
658
|
}
|
|
@@ -2,4 +2,6 @@
|
|
|
2
2
|
<item name="onekey_native_scroll_coordinator_consumed_offsets" type="id" />
|
|
3
3
|
<item name="onekey_native_scroll_coordinator_offset_listener" type="id" />
|
|
4
4
|
<item name="onekey_native_scroll_coordinator_refresh_inset" type="id" />
|
|
5
|
+
<item name="onekey_native_scroll_coordinator_command_listener" type="id" />
|
|
6
|
+
<item name="onekey_native_scroll_coordinator_command_cancel_listener" type="id" />
|
|
5
7
|
</resources>
|
package/docs/SPEC.md
CHANGED
|
@@ -3,53 +3,59 @@
|
|
|
3
3
|
Existing PagerView and CollapsiblePagerView APIs are documented in README.md.
|
|
4
4
|
The sections below define native coordination boundaries without new React props.
|
|
5
5
|
|
|
6
|
-
## Smooth per-page
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
the
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
6
|
+
## Smooth shared-header and per-page body memory
|
|
7
|
+
|
|
8
|
+
With nativeSmoothHeaderScrollEnabled, the header collapse C is shared across all
|
|
9
|
+
pages and the available collapse distance is D. Each page separately remembers
|
|
10
|
+
its sticky-body reading distance B (unvisited pages default to zero). Outside
|
|
11
|
+
pull overscroll, the rendered whole-page distance is Q = C + effectiveB.
|
|
12
|
+
B denotes the saved reading position. For an owned vertical LinearLayoutManager
|
|
13
|
+
RecyclerView, restoration uses the first visible adapter position and its
|
|
14
|
+
decorated top relative to padding; scrollbar offset estimates MUST NOT decide
|
|
15
|
+
completion of that anchor restoration.
|
|
16
|
+
When C = D, selection restores the destination's saved B. When C < D, effectiveB
|
|
17
|
+
is zero while the previous saved B remains suspended. Horizontal selection by
|
|
18
|
+
tap, swipe or an existing programmatic command MUST preserve C throughout.
|
|
19
|
+
|
|
20
|
+
Alignment, prefetch, replacement, inset changes and pending restoration MUST NOT
|
|
21
|
+
commit new B. Actual consumed vertical scrolling takes over the visible body
|
|
22
|
+
position; reaching full collapse during that gesture MUST NOT resurrect the old
|
|
23
|
+
suspended B. Selecting a page anew at full collapse may restore its saved B.
|
|
24
|
+
Valid explicit native scroll commands, including same-offset commands, cancel
|
|
25
|
+
only their current owned restoration and take over body memory. Invalid commands
|
|
26
|
+
and stale owners do not affect another page. Existing command coordinate systems
|
|
27
|
+
are unchanged; in particular NativeScroller iOS uses physical offsets whereas
|
|
28
|
+
NativeList offset commands exclude the content-start inset.
|
|
29
|
+
|
|
30
|
+
Transitions use immutable destination memory and the source's actual displayed
|
|
31
|
+
position. Cancellation restores that source presentation, even when a cached B
|
|
32
|
+
was temporarily unreachable. Loading or zero geometry preserves pending intent;
|
|
33
|
+
a genuinely short page clamps its display without silently replacing saved B.
|
|
34
|
+
Cancelling a horizontal gesture invalidates queued callbacks, but preserves
|
|
35
|
+
unreachable reading intent until real vertical consumption or a valid command
|
|
36
|
+
takes over; later usable geometry may resume it.
|
|
37
|
+
Late callbacks cannot revive cancelled restoration or erase a newer request.
|
|
38
|
+
Observers and commands must match page key, view identity and generation.
|
|
39
|
+
Removed or recycled owners cannot apply callbacks to another page; recycling
|
|
40
|
+
resets owned memory.
|
|
41
|
+
Legacy mode and pagers without a collapsible header retain their existing
|
|
42
|
+
behavior. Vertical scrolling, refresh, snapping and repeated-current-tab behavior
|
|
43
|
+
are unchanged. This state belongs to native UI instances, with no new React prop
|
|
44
|
+
or per-frame JavaScript synchronization.
|
|
45
|
+
|
|
46
|
+
## Current-page top commands
|
|
47
|
+
|
|
48
|
+
`scrollToPageTop(options?: Readonly<{ animated?: boolean }>)` restores the current
|
|
49
|
+
page to C = 0 and B = 0. `scrollToStickyTop(options?: Readonly<{ animated?: boolean }>)`
|
|
50
|
+
restores it to C = D and B = 0, including from a partially expanded header.
|
|
51
|
+
Animation defaults to true. Neither command clears another page's memory.
|
|
52
|
+
Both commands require a stable, attached current owner; horizontal transitions
|
|
53
|
+
or missing owners reject them rather than queueing a command for another page.
|
|
54
|
+
Acceptance cancels older owned list commands and pending restoration before the
|
|
55
|
+
new target is established. Same-target commands also take over old reading
|
|
56
|
+
intent. Real vertical consumption, a newer valid command, or owner detachment
|
|
57
|
+
releases the target. Existing NativeList and NativeScroller public coordinates
|
|
58
|
+
are unchanged. The same page-top/sticky-top destinations are available without smooth-header mode.
|
|
53
59
|
|
|
54
60
|
## Independent NativeScroller migration
|
|
55
61
|
|
|
@@ -503,7 +509,7 @@ the upper bound to the current content height, viewport and applied insets. A
|
|
|
503
509
|
cache captured before rows were removed MUST NOT restore an offset below the new
|
|
504
510
|
content bottom, including when removal occurs during a page transition. Valid
|
|
505
511
|
deep offsets and pull-overscroll behavior are preserved; smooth-header selection
|
|
506
|
-
follows the per-page
|
|
512
|
+
follows the shared-header and per-page body-memory contract above.
|
|
507
513
|
This check runs only on explicit restoration, not on scroll frames; UIKit pull
|
|
508
514
|
overscroll and refresh settlement retain their existing ownership. An unmeasured
|
|
509
515
|
zero-height viewport defers this upper-bound limit to a later restoration.
|
|
@@ -1481,6 +1481,19 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1481
1481
|
NSArray<NSString *> *_pageKeys;
|
|
1482
1482
|
NSString *_retainedPages;
|
|
1483
1483
|
NSMutableDictionary<NSString *, NSNumber *> *_pageOffsets;
|
|
1484
|
+
NSMutableSet<NSString *> *_commandBodyKeys;
|
|
1485
|
+
__weak UIScrollView *_pagerTopScrollView;
|
|
1486
|
+
NSString *_pagerTopPageKey;
|
|
1487
|
+
NSUInteger _pagerTopGeneration;
|
|
1488
|
+
NSInteger _pagerTopPageIndex;
|
|
1489
|
+
CGFloat _pagerTopLogicalTarget;
|
|
1490
|
+
BOOL _dispatchingPagerTop;
|
|
1491
|
+
NSUInteger _pagerTopToken;
|
|
1492
|
+
NSMutableSet<NSString *> *_alignedBodyKeys;
|
|
1493
|
+
NSMutableSet<NSString *> *_suspendedBodyKeys;
|
|
1494
|
+
CGFloat _transitionHeaderOffset;
|
|
1495
|
+
CGFloat _transitionSourceDisplayBody;
|
|
1496
|
+
NSMutableDictionary<NSString *, NSNumber *> *_displayBodyOverrides;
|
|
1484
1497
|
NSMapTable<UIScrollView *, NSValue *> *_originalInsets;
|
|
1485
1498
|
NSMapTable<UIScrollView *, UIRefreshControl *> *_managedRefreshControls;
|
|
1486
1499
|
NSHashTable<UIScrollView *> *_refreshControlObservedScrollViews;
|
|
@@ -1540,6 +1553,12 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1540
1553
|
_logicalChildren = [NSMutableArray new];
|
|
1541
1554
|
_pageControllers = [NSMutableArray new];
|
|
1542
1555
|
_pageOffsets = [NSMutableDictionary new];
|
|
1556
|
+
_commandBodyKeys = [NSMutableSet new];
|
|
1557
|
+
_alignedBodyKeys = [NSMutableSet new];
|
|
1558
|
+
_suspendedBodyKeys = [NSMutableSet new];
|
|
1559
|
+
_displayBodyOverrides = [NSMutableDictionary new];
|
|
1560
|
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(nativeListScrollCommandAccepted:)
|
|
1561
|
+
name:@"OneKeyNativeListScrollCommandAccepted" object:nil];
|
|
1543
1562
|
_pendingPageRestoreKeys = [NSMutableSet new];
|
|
1544
1563
|
_releasedPageScrollStates = [NSMutableDictionary new];
|
|
1545
1564
|
_mountingRemovedScrollViews = [NSHashTable weakObjectsHashTable];
|
|
@@ -1684,6 +1703,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1684
1703
|
|
|
1685
1704
|
- (void)dealloc
|
|
1686
1705
|
{
|
|
1706
|
+
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"OneKeyNativeListScrollCommandAccepted" object:nil];
|
|
1687
1707
|
for (UIScrollView *scrollView in _originalInsets.keyEnumerator) {
|
|
1688
1708
|
[self updateNativeScrollerViewport:scrollView stickyHeight:0];
|
|
1689
1709
|
}
|
|
@@ -1947,9 +1967,12 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1947
1967
|
|
|
1948
1968
|
- (void)beginPageStateTransition
|
|
1949
1969
|
{
|
|
1970
|
+
[self cancelPagerTop];
|
|
1950
1971
|
if (!_nativeSmoothHeaderScrollEnabled || _headerHeight <= 0 || _transitionPageOffsets != nil) return;
|
|
1972
|
+
_transitionSourceDisplayBody = MAX(_observedScrollView.contentOffset.y + _observedScrollView.contentInset.top - _headerHeight, 0);
|
|
1951
1973
|
[self detachScrollObserver];
|
|
1952
1974
|
_transitionSourceIndex = _currentIndex;
|
|
1975
|
+
_transitionHeaderOffset = _headerOffset;
|
|
1953
1976
|
_transitionPageOffsets = [_pageOffsets copy];
|
|
1954
1977
|
_transitionCompensatedPages = [NSMutableIndexSet new];
|
|
1955
1978
|
#if DEBUG
|
|
@@ -1972,9 +1995,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
1972
1995
|
}
|
|
1973
1996
|
CGFloat firstQ = [_transitionPageOffsets[[self pageKeyForIndex:first]] doubleValue];
|
|
1974
1997
|
CGFloat secondQ = [_transitionPageOffsets[[self pageKeyForIndex:second]] doubleValue];
|
|
1975
|
-
|
|
1976
|
-
CGFloat secondH = RNCClamp(secondQ, 0, _headerHeight);
|
|
1977
|
-
_headerOffset = firstH + (secondH - firstH) * fraction;
|
|
1998
|
+
_headerOffset = _transitionHeaderOffset;
|
|
1978
1999
|
#if DEBUG
|
|
1979
2000
|
NSInteger bucket = (NSInteger)floor(fraction * 4);
|
|
1980
2001
|
if (_transitionDiagBucket != bucket) {
|
|
@@ -2008,7 +2029,10 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2008
2029
|
{
|
|
2009
2030
|
if (_transitionPageOffsets == nil) return;
|
|
2010
2031
|
_finishingPageStateTransition = YES;
|
|
2011
|
-
_headerOffset =
|
|
2032
|
+
_headerOffset = _transitionHeaderOffset;
|
|
2033
|
+
if (_currentIndex == _transitionSourceIndex) _displayBodyOverrides[self.currentPageKey] = @(_transitionSourceDisplayBody);
|
|
2034
|
+
else [_displayBodyOverrides removeObjectForKey:self.currentPageKey];
|
|
2035
|
+
if (_headerOffset >= _headerHeight) [_suspendedBodyKeys removeObject:self.currentPageKey];
|
|
2012
2036
|
_syntheticPageRestore = YES;
|
|
2013
2037
|
// Both completion and cancellation undo every temporary viewport offset.
|
|
2014
2038
|
for (NSUInteger index = _transitionCompensatedPages.firstIndex; index != NSNotFound;
|
|
@@ -2016,10 +2040,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2016
2040
|
UIScrollView *scroll = [self verticalScrollViewForPageAtIndex:index];
|
|
2017
2041
|
if (scroll == nil) continue;
|
|
2018
2042
|
[self applyInsetsToScrollView:scroll pageIndex:index restore:YES];
|
|
2019
|
-
|
|
2020
|
-
if (![_pendingPageRestoreKeys containsObject:key]) {
|
|
2021
|
-
_pageOffsets[key] = @(scroll.contentOffset.y + scroll.contentInset.top);
|
|
2022
|
-
}
|
|
2043
|
+
|
|
2023
2044
|
}
|
|
2024
2045
|
_syntheticPageRestore = NO;
|
|
2025
2046
|
_finishingPageStateTransition = NO;
|
|
@@ -2083,8 +2104,8 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2083
2104
|
(!_nativeSmoothHeaderScrollEnabled ||
|
|
2084
2105
|
(_observedPageGeneration == _generation && _observedPageIndex == index &&
|
|
2085
2106
|
[_observedPageKey isEqualToString:pageKey]));
|
|
2086
|
-
if (_transitionPageOffsets == nil && !_syntheticPageRestore &&
|
|
2087
|
-
|
|
2107
|
+
if (!_nativeSmoothHeaderScrollEnabled && _transitionPageOffsets == nil && !_syntheticPageRestore &&
|
|
2108
|
+
![_pendingPageRestoreKeys containsObject:pageKey] &&
|
|
2088
2109
|
(ownsObservedPage || _pageOffsets[pageKey] == nil)) {
|
|
2089
2110
|
[self offsetDiag:@"mount-release-save-before" page:index scroll:scrollView];
|
|
2090
2111
|
_pageOffsets[pageKey] = @(scrollView.contentOffset.y + scrollView.contentInset.top);
|
|
@@ -2426,6 +2447,10 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2426
2447
|
_pagerScrollView = nil;
|
|
2427
2448
|
[super prepareForRecycle];
|
|
2428
2449
|
[_pageOffsets removeAllObjects];
|
|
2450
|
+
[_commandBodyKeys removeAllObjects];
|
|
2451
|
+
[_alignedBodyKeys removeAllObjects];
|
|
2452
|
+
[_suspendedBodyKeys removeAllObjects];
|
|
2453
|
+
[_displayBodyOverrides removeAllObjects];
|
|
2429
2454
|
[_pendingPageRestoreKeys removeAllObjects];
|
|
2430
2455
|
_transitionPageOffsets = nil;
|
|
2431
2456
|
_transitionCompensatedPages = nil;
|
|
@@ -2855,7 +2880,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2855
2880
|
[self applyInsetsToScrollView:candidate pageIndex:_currentIndex restore:YES];
|
|
2856
2881
|
[candidate addObserver:self
|
|
2857
2882
|
forKeyPath:@"contentOffset"
|
|
2858
|
-
options:NSKeyValueObservingOptionNew
|
|
2883
|
+
options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew
|
|
2859
2884
|
context:RNCCollapsiblePagerContentOffsetContext];
|
|
2860
2885
|
[candidate addObserver:self
|
|
2861
2886
|
forKeyPath:@"contentInset"
|
|
@@ -2875,6 +2900,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2875
2900
|
|
|
2876
2901
|
- (void)detachScrollObserver
|
|
2877
2902
|
{
|
|
2903
|
+
[self cancelPagerTop];
|
|
2878
2904
|
UIScrollView *scrollView = _observedScrollView;
|
|
2879
2905
|
if (scrollView != nil) {
|
|
2880
2906
|
[scrollView.panGestureRecognizer removeTarget:self action:@selector(observedListPanChanged:)];
|
|
@@ -2883,9 +2909,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2883
2909
|
BOOL ownerKeyExists = ownerKey != nil && ([_pageKeys containsObject:ownerKey] ||
|
|
2884
2910
|
(_observedPageIndex >= 0 && _observedPageIndex < _pageControllers.count &&
|
|
2885
2911
|
[[self pageKeyForIndex:_observedPageIndex] isEqualToString:ownerKey]));
|
|
2886
|
-
if (ownerKey != nil &&
|
|
2887
|
-
(ownerKeyExists && _observedPageGeneration == _generation && _transitionPageOffsets == nil &&
|
|
2888
|
-
!_syntheticPageRestore && ![_pendingPageRestoreKeys containsObject:ownerKey]))) {
|
|
2912
|
+
if (ownerKey != nil && !_nativeSmoothHeaderScrollEnabled) {
|
|
2889
2913
|
_pageOffsets[ownerKey] = @(scrollView.contentOffset.y + scrollView.contentInset.top);
|
|
2890
2914
|
}
|
|
2891
2915
|
[self offsetDiag:@"detach-save-after" page:_currentIndex scroll:scrollView];
|
|
@@ -2901,6 +2925,9 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
2901
2925
|
context:RNCCollapsiblePagerContentOffsetContext];
|
|
2902
2926
|
}
|
|
2903
2927
|
}
|
|
2928
|
+
if (!_nativeSmoothHeaderScrollEnabled && _observedPageKey != nil) {
|
|
2929
|
+
[_alignedBodyKeys removeObject:_observedPageKey];
|
|
2930
|
+
}
|
|
2904
2931
|
_observingContentOffset = NO;
|
|
2905
2932
|
_observedScrollView = nil;
|
|
2906
2933
|
_observedPageKey = nil;
|
|
@@ -3331,6 +3358,8 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3331
3358
|
if (pageIndex == _currentIndex) [self updateHeaderForScrollView:scrollView];
|
|
3332
3359
|
return;
|
|
3333
3360
|
}
|
|
3361
|
+
BOOL previousSyntheticRestore = _syntheticPageRestore;
|
|
3362
|
+
if (_nativeSmoothHeaderScrollEnabled || [_alignedBodyKeys containsObject:pageKey]) _syntheticPageRestore = YES;
|
|
3334
3363
|
[self offsetDiag:@"inset-assignment-before" page:pageIndex scroll:scrollView];
|
|
3335
3364
|
scrollView.contentInset = next;
|
|
3336
3365
|
[self offsetDiag:@"inset-assignment-after" page:pageIndex scroll:scrollView];
|
|
@@ -3340,6 +3369,7 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3340
3369
|
scrollView.alwaysBounceVertical = YES;
|
|
3341
3370
|
|
|
3342
3371
|
CGFloat targetOffset = previousLogicalOffset - next.top;
|
|
3372
|
+
CGFloat intendedLogicalOffset = previousLogicalOffset;
|
|
3343
3373
|
if (restore) {
|
|
3344
3374
|
NSNumber *saved = _transitionPageOffsets != nil
|
|
3345
3375
|
? _transitionPageOffsets[pageKey] : _pageOffsets[pageKey];
|
|
@@ -3347,13 +3377,17 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3347
3377
|
// to content start so a round trip does not add that height difference.
|
|
3348
3378
|
CGFloat restoredLogicalOffset;
|
|
3349
3379
|
if (_nativeSmoothHeaderScrollEnabled && _headerHeight > 0) {
|
|
3350
|
-
|
|
3351
|
-
if (
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3380
|
+
[_alignedBodyKeys addObject:pageKey];
|
|
3381
|
+
if (_headerOffset < _headerHeight && saved.doubleValue > 0) [_suspendedBodyKeys addObject:pageKey];
|
|
3382
|
+
CGFloat body = saved.doubleValue;
|
|
3383
|
+
if (_transitionPageOffsets != nil && pageIndex == _transitionSourceIndex) body = _transitionSourceDisplayBody;
|
|
3384
|
+
else if (_transitionPageOffsets != nil) [_displayBodyOverrides removeObjectForKey:pageKey];
|
|
3385
|
+
else if (_displayBodyOverrides[pageKey] != nil) body = _displayBodyOverrides[pageKey].doubleValue;
|
|
3386
|
+
restoredLogicalOffset = _headerOffset + (_headerOffset >= _headerHeight ? body : 0);
|
|
3387
|
+
if (_transitionPageOffsets != nil) [_transitionCompensatedPages addIndex:pageIndex];
|
|
3355
3388
|
if (deferredReleasedIdentity || scrollView.bounds.size.height <= 0 || scrollView.contentSize.height <= 0) {
|
|
3356
3389
|
[_pendingPageRestoreKeys addObject:pageKey];
|
|
3390
|
+
_syntheticPageRestore = previousSyntheticRestore;
|
|
3357
3391
|
return;
|
|
3358
3392
|
}
|
|
3359
3393
|
[_pendingPageRestoreKeys removeObject:pageKey];
|
|
@@ -3363,6 +3397,12 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3363
3397
|
#if DEBUG
|
|
3364
3398
|
[self offsetDiag:[NSString stringWithFormat:@"restore-candidate-saved=%.4f-headerAlignedLogical=%.4f", saved.doubleValue, restoredLogicalOffset] page:pageIndex scroll:scrollView];
|
|
3365
3399
|
#endif
|
|
3400
|
+
intendedLogicalOffset = restoredLogicalOffset;
|
|
3401
|
+
// Cancellation restores the visible source, while retaining its unreachable reading intent.
|
|
3402
|
+
if (_nativeSmoothHeaderScrollEnabled && _headerOffset >= _headerHeight &&
|
|
3403
|
+
_displayBodyOverrides[pageKey] != nil) {
|
|
3404
|
+
intendedLogicalOffset = MAX(intendedLogicalOffset, _headerOffset + _pageOffsets[pageKey].doubleValue);
|
|
3405
|
+
}
|
|
3366
3406
|
targetOffset = restoredLogicalOffset - next.top;
|
|
3367
3407
|
if (!_nativeSmoothHeaderScrollEnabled || _headerHeight <= 0) {
|
|
3368
3408
|
targetOffset = MAX(targetOffset, -next.top + _headerOffset);
|
|
@@ -3387,7 +3427,15 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3387
3427
|
if (restore || previousTopInset != next.top) {
|
|
3388
3428
|
[scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, targetOffset) animated:NO];
|
|
3389
3429
|
}
|
|
3390
|
-
if (
|
|
3430
|
+
if (_nativeSmoothHeaderScrollEnabled && restore && targetOffset + next.top + 0.5 < intendedLogicalOffset) {
|
|
3431
|
+
[_pendingPageRestoreKeys addObject:pageKey];
|
|
3432
|
+
}
|
|
3433
|
+
_syntheticPageRestore = previousSyntheticRestore;
|
|
3434
|
+
if (pageIndex == _currentIndex) {
|
|
3435
|
+
_currentLogicalOffset = scrollView.contentOffset.y + scrollView.contentInset.top;
|
|
3436
|
+
if (!_nativeSmoothHeaderScrollEnabled) [self updateHeaderForScrollView:scrollView];
|
|
3437
|
+
else [self applyHeaderOffset];
|
|
3438
|
+
}
|
|
3391
3439
|
[self offsetDiag:@"restore-post" page:pageIndex scroll:scrollView];
|
|
3392
3440
|
}
|
|
3393
3441
|
|
|
@@ -3398,20 +3446,66 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3398
3446
|
}
|
|
3399
3447
|
}
|
|
3400
3448
|
|
|
3449
|
+
- (void)nativeListScrollCommandAccepted:(NSNotification *)notification
|
|
3450
|
+
{
|
|
3451
|
+
UIScrollView *scrollView = notification.object;
|
|
3452
|
+
if (scrollView != _observedScrollView ||
|
|
3453
|
+
_observedPageKey == nil || ![_observedPageKey isEqualToString:self.currentPageKey] ||
|
|
3454
|
+
_observedPageIndex != _currentIndex || _observedPageGeneration != _generation ||
|
|
3455
|
+
_transitioning || _isPagerDragging || _transitionPageOffsets != nil || _syntheticPageRestore) return;
|
|
3456
|
+
NSInteger phase = [notification.userInfo[@"phase"] integerValue];
|
|
3457
|
+
if ([self matchesPagerTop:scrollView]) {
|
|
3458
|
+
if (phase == 0) [self cancelPagerTop];
|
|
3459
|
+
else return;
|
|
3460
|
+
}
|
|
3461
|
+
if (phase == 0) [_alignedBodyKeys removeObject:_observedPageKey];
|
|
3462
|
+
if (!_nativeSmoothHeaderScrollEnabled) return;
|
|
3463
|
+
_currentLogicalOffset = scrollView.contentOffset.y + scrollView.contentInset.top;
|
|
3464
|
+
if (phase == 1) { [_commandBodyKeys addObject:_observedPageKey]; return; }
|
|
3465
|
+
if (phase == 2) {
|
|
3466
|
+
if (![_commandBodyKeys containsObject:_observedPageKey]) return;
|
|
3467
|
+
_pageOffsets[_observedPageKey] = @(MAX(_currentLogicalOffset - _headerHeight, 0));
|
|
3468
|
+
[self updateHeaderForScrollView:scrollView];
|
|
3469
|
+
[_commandBodyKeys removeObject:_observedPageKey];
|
|
3470
|
+
return;
|
|
3471
|
+
}
|
|
3472
|
+
[_commandBodyKeys removeObject:_observedPageKey];
|
|
3473
|
+
[_pendingPageRestoreKeys removeObject:_observedPageKey];
|
|
3474
|
+
[_alignedBodyKeys removeObject:_observedPageKey];
|
|
3475
|
+
[_suspendedBodyKeys removeObject:_observedPageKey];
|
|
3476
|
+
[_displayBodyOverrides removeObjectForKey:_observedPageKey];
|
|
3477
|
+
_currentLogicalOffset = scrollView.contentOffset.y + scrollView.contentInset.top;
|
|
3478
|
+
BOOL explicitTop = [notification.userInfo[@"explicitTop"] boolValue];
|
|
3479
|
+
_pageOffsets[_observedPageKey] = @(explicitTop ? 0 : MAX(_currentLogicalOffset - _headerHeight, 0));
|
|
3480
|
+
if (explicitTop) {
|
|
3481
|
+
_headerOffset = 0;
|
|
3482
|
+
[self applyHeaderOffset];
|
|
3483
|
+
}
|
|
3484
|
+
[self offsetDiag:@"list-command-body-takeover" page:_currentIndex scroll:scrollView];
|
|
3485
|
+
}
|
|
3486
|
+
|
|
3401
3487
|
- (void)nativeScrollerWillReceiveScrollCommand:(RNCNativeScrollerComponentView *)scroller
|
|
3402
3488
|
{
|
|
3403
3489
|
UIScrollView *scrollView = scroller.scrollView;
|
|
3404
3490
|
NSString *ownerKey = _observedPageKey;
|
|
3405
|
-
if (
|
|
3491
|
+
if (scrollView != _observedScrollView ||
|
|
3406
3492
|
ownerKey == nil || ![ownerKey isEqualToString:self.currentPageKey] ||
|
|
3407
3493
|
_observedPageIndex != _currentIndex || _currentIndex < 0 || _currentIndex >= _pageControllers.count ||
|
|
3408
3494
|
_observedPageGeneration != _generation || _transitioning || _isPagerDragging ||
|
|
3409
|
-
_transitionPageOffsets != nil || _syntheticPageRestore
|
|
3410
|
-
|
|
3495
|
+
_transitionPageOffsets != nil || _syntheticPageRestore) return;
|
|
3496
|
+
if (!_dispatchingPagerTop) {
|
|
3497
|
+
[self cancelPagerTop];
|
|
3498
|
+
[_alignedBodyKeys removeObject:ownerKey];
|
|
3499
|
+
}
|
|
3500
|
+
if (!_nativeSmoothHeaderScrollEnabled) return;
|
|
3411
3501
|
[self offsetDiag:@"command-pending-cancel-before" page:_observedPageIndex scroll:scrollView];
|
|
3412
3502
|
[_pendingPageRestoreKeys removeObject:ownerKey];
|
|
3413
3503
|
_currentLogicalOffset = scrollView.contentOffset.y + scrollView.contentInset.top;
|
|
3414
|
-
|
|
3504
|
+
[_commandBodyKeys removeObject:ownerKey];
|
|
3505
|
+
[_alignedBodyKeys removeObject:ownerKey];
|
|
3506
|
+
[_suspendedBodyKeys removeObject:ownerKey];
|
|
3507
|
+
[_displayBodyOverrides removeObjectForKey:ownerKey];
|
|
3508
|
+
_pageOffsets[ownerKey] = @(MAX(_currentLogicalOffset - _headerHeight, 0));
|
|
3415
3509
|
[self updateHeaderForScrollView:scrollView];
|
|
3416
3510
|
[self offsetDiag:@"command-pending-cancel-after" page:_observedPageIndex scroll:scrollView];
|
|
3417
3511
|
}
|
|
@@ -3475,36 +3569,76 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3475
3569
|
return;
|
|
3476
3570
|
}
|
|
3477
3571
|
if (context == RNCCollapsiblePagerContentOffsetContext && object == _observedScrollView) {
|
|
3478
|
-
if (_nativeSmoothHeaderScrollEnabled &&
|
|
3572
|
+
if ((_nativeSmoothHeaderScrollEnabled || [_alignedBodyKeys containsObject:_observedPageKey]) &&
|
|
3479
3573
|
(_observedPageGeneration != _generation || _observedPageKey == nil ||
|
|
3480
3574
|
_observedPageIndex != _currentIndex || ![_observedPageKey isEqualToString:self.currentPageKey] ||
|
|
3481
3575
|
_transitioning || _isPagerDragging ||
|
|
3482
3576
|
_transitionPageOffsets != nil || _syntheticPageRestore)) return;
|
|
3577
|
+
UIScrollView *ownedScroll = (UIScrollView *)object;
|
|
3578
|
+
NSValue *oldPoint = change[NSKeyValueChangeOldKey];
|
|
3579
|
+
NSValue *newPoint = change[NSKeyValueChangeNewKey];
|
|
3580
|
+
if ([keyPath isEqualToString:@"contentOffset"] && [self matchesPagerTop:ownedScroll] && ownedScroll.panGestureRecognizer.state == UIGestureRecognizerStateChanged &&
|
|
3581
|
+
[oldPoint isKindOfClass:NSValue.class] && [newPoint isKindOfClass:NSValue.class] &&
|
|
3582
|
+
oldPoint.CGPointValue.y != newPoint.CGPointValue.y) {
|
|
3583
|
+
CGPoint interruptedOffset = ownedScroll.contentOffset;
|
|
3584
|
+
[self cancelPagerTop];
|
|
3585
|
+
[ownedScroll setContentOffset:interruptedOffset animated:NO];
|
|
3586
|
+
}
|
|
3587
|
+
if ([keyPath isEqualToString:@"contentOffset"] &&
|
|
3588
|
+
ownedScroll.panGestureRecognizer.state == UIGestureRecognizerStateChanged &&
|
|
3589
|
+
[oldPoint isKindOfClass:NSValue.class] && [newPoint isKindOfClass:NSValue.class] &&
|
|
3590
|
+
oldPoint.CGPointValue.y != newPoint.CGPointValue.y) {
|
|
3591
|
+
[_alignedBodyKeys removeObject:_observedPageKey];
|
|
3592
|
+
}
|
|
3593
|
+
if (_nativeSmoothHeaderScrollEnabled && [keyPath isEqualToString:@"contentOffset"] &&
|
|
3594
|
+
ownedScroll.panGestureRecognizer.state == UIGestureRecognizerStateChanged &&
|
|
3595
|
+
[oldPoint isKindOfClass:NSValue.class] && [newPoint isKindOfClass:NSValue.class] &&
|
|
3596
|
+
oldPoint.CGPointValue.y != newPoint.CGPointValue.y) {
|
|
3597
|
+
[self cancelPagerTop];
|
|
3598
|
+
[_commandBodyKeys removeObject:_observedPageKey];
|
|
3599
|
+
[_pendingPageRestoreKeys removeObject:_observedPageKey];
|
|
3600
|
+
[_alignedBodyKeys removeObject:_observedPageKey];
|
|
3601
|
+
[_suspendedBodyKeys removeObject:_observedPageKey];
|
|
3602
|
+
[_displayBodyOverrides removeObjectForKey:_observedPageKey];
|
|
3603
|
+
}
|
|
3483
3604
|
if (_nativeSmoothHeaderScrollEnabled && [_pendingPageRestoreKeys containsObject:_observedPageKey]) {
|
|
3484
|
-
if ([keyPath isEqualToString:@"contentSize"]
|
|
3605
|
+
if ([keyPath isEqualToString:@"contentSize"] &&
|
|
3606
|
+
![change[NSKeyValueChangeOldKey] isEqual:change[NSKeyValueChangeNewKey]]) {
|
|
3607
|
+
if (_headerOffset >= _headerHeight) [_displayBodyOverrides removeObjectForKey:_observedPageKey];
|
|
3485
3608
|
[self applyInsetsToScrollView:_observedScrollView pageIndex:_observedPageIndex restore:YES];
|
|
3486
3609
|
}
|
|
3487
3610
|
return;
|
|
3488
3611
|
}
|
|
3489
3612
|
if ([keyPath isEqualToString:@"contentInset"]) {
|
|
3490
|
-
[self updateHeaderForScrollView:(UIScrollView *)object];
|
|
3613
|
+
if (!_nativeSmoothHeaderScrollEnabled) [self updateHeaderForScrollView:(UIScrollView *)object];
|
|
3491
3614
|
return;
|
|
3492
3615
|
}
|
|
3493
3616
|
if ([keyPath isEqualToString:@"contentSize"]) {
|
|
3494
3617
|
NSValue *oldSize = change[NSKeyValueChangeOldKey];
|
|
3495
3618
|
NSValue *newSize = change[NSKeyValueChangeNewKey];
|
|
3496
3619
|
if (![oldSize isEqual:newSize]) {
|
|
3497
|
-
|
|
3620
|
+
BOOL restoreAlignedBody =
|
|
3621
|
+
_observedPageGeneration == _generation && _observedPageIndex == _currentIndex &&
|
|
3622
|
+
_observedPageKey != nil && [_observedPageKey isEqualToString:self.currentPageKey] &&
|
|
3623
|
+
[_alignedBodyKeys containsObject:_observedPageKey] &&
|
|
3624
|
+
![_commandBodyKeys containsObject:_observedPageKey] &&
|
|
3625
|
+
_observedScrollView.panGestureRecognizer.state != UIGestureRecognizerStateChanged &&
|
|
3626
|
+
!_observedScrollView.isDragging && !_observedScrollView.isDecelerating;
|
|
3627
|
+
[self applyInsetsToScrollView:_observedScrollView pageIndex:_currentIndex restore:restoreAlignedBody];
|
|
3498
3628
|
}
|
|
3499
3629
|
return;
|
|
3500
3630
|
}
|
|
3501
3631
|
UIScrollView *scrollView = (UIScrollView *)object;
|
|
3502
3632
|
_currentLogicalOffset = scrollView.contentOffset.y + scrollView.contentInset.top;
|
|
3503
3633
|
#if DEBUG
|
|
3504
|
-
BOOL offsetDiagChanged = _pageOffsets[self.currentPageKey] == nil || _pageOffsets[self.currentPageKey].doubleValue != _currentLogicalOffset;
|
|
3634
|
+
BOOL offsetDiagChanged = _pageOffsets[self.currentPageKey] == nil || _pageOffsets[self.currentPageKey].doubleValue != (_nativeSmoothHeaderScrollEnabled ? MAX(_currentLogicalOffset - _headerHeight, 0) : _currentLogicalOffset);
|
|
3505
3635
|
if (offsetDiagChanged) [self offsetDiag:@"kvo-cache-before" page:_currentIndex scroll:scrollView];
|
|
3506
3636
|
#endif
|
|
3507
|
-
|
|
3637
|
+
if ([_alignedBodyKeys containsObject:_observedPageKey] ||
|
|
3638
|
+
(_nativeSmoothHeaderScrollEnabled && scrollView.panGestureRecognizer.state != UIGestureRecognizerStateChanged &&
|
|
3639
|
+
!scrollView.isDecelerating && ![_commandBodyKeys containsObject:_observedPageKey])) return;
|
|
3640
|
+
_pageOffsets[_nativeSmoothHeaderScrollEnabled ? _observedPageKey : self.currentPageKey] =
|
|
3641
|
+
@(_nativeSmoothHeaderScrollEnabled ? MAX(_currentLogicalOffset - _headerHeight, 0) : _currentLogicalOffset);
|
|
3508
3642
|
#if DEBUG
|
|
3509
3643
|
if (offsetDiagChanged) [self offsetDiag:@"kvo-cache-after" page:_currentIndex scroll:scrollView];
|
|
3510
3644
|
#endif
|
|
@@ -3516,8 +3650,16 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3516
3650
|
|
|
3517
3651
|
- (void)updateHeaderForScrollView:(UIScrollView *)scrollView
|
|
3518
3652
|
{
|
|
3519
|
-
if (
|
|
3520
|
-
|
|
3653
|
+
if ([self matchesPagerTop:scrollView]) {
|
|
3654
|
+
_currentLogicalOffset = scrollView.contentOffset.y + scrollView.contentInset.top;
|
|
3655
|
+
_headerOffset = _pagerTopLogicalTarget;
|
|
3656
|
+
[self applyHeaderOffset];
|
|
3657
|
+
[self finishPagerTopIfReached];
|
|
3658
|
+
return;
|
|
3659
|
+
}
|
|
3660
|
+
if ([_alignedBodyKeys containsObject:self.currentPageKey] ||
|
|
3661
|
+
(_nativeSmoothHeaderScrollEnabled && (_syntheticPageRestore || _transitionPageOffsets != nil ||
|
|
3662
|
+
[_pendingPageRestoreKeys containsObject:self.currentPageKey]))) return;
|
|
3521
3663
|
CGFloat logicalOffset = scrollView.contentOffset.y + scrollView.contentInset.top;
|
|
3522
3664
|
_currentLogicalOffset = logicalOffset;
|
|
3523
3665
|
_headerOffset = MIN(MAX(logicalOffset, 0), _headerHeight);
|
|
@@ -3963,6 +4105,77 @@ static void RNCLogNativeTabScrollBoundary(NSString *owner,
|
|
|
3963
4105
|
RCTRNCCollapsiblePagerViewHandleCommand(self, commandName, args);
|
|
3964
4106
|
}
|
|
3965
4107
|
|
|
4108
|
+
- (BOOL)matchesPagerTop:(UIScrollView *)scrollView
|
|
4109
|
+
{
|
|
4110
|
+
return scrollView != nil && scrollView == _pagerTopScrollView && scrollView == _observedScrollView &&
|
|
4111
|
+
_pagerTopPageKey != nil && [_pagerTopPageKey isEqualToString:self.currentPageKey] &&
|
|
4112
|
+
[_observedPageKey isEqualToString:_pagerTopPageKey] && _pagerTopPageIndex == _currentIndex &&
|
|
4113
|
+
_observedPageIndex == _currentIndex && _pagerTopGeneration == _generation &&
|
|
4114
|
+
_observedPageGeneration == _generation && scrollView.window != nil;
|
|
4115
|
+
}
|
|
4116
|
+
|
|
4117
|
+
- (void)cancelPagerTop
|
|
4118
|
+
{
|
|
4119
|
+
if (_pagerTopPageKey != nil) [_commandBodyKeys removeObject:_pagerTopPageKey];
|
|
4120
|
+
_pagerTopScrollView = nil;
|
|
4121
|
+
_pagerTopPageKey = nil;
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
- (void)finishPagerTopIfReached
|
|
4125
|
+
{
|
|
4126
|
+
UIScrollView *scrollView = _pagerTopScrollView;
|
|
4127
|
+
if (_dispatchingPagerTop || ![self matchesPagerTop:scrollView]) return;
|
|
4128
|
+
CGFloat logical = scrollView.contentOffset.y + scrollView.contentInset.top;
|
|
4129
|
+
if (fabs(logical - _pagerTopLogicalTarget) > 0.5) return;
|
|
4130
|
+
_pageOffsets[_pagerTopPageKey] = @(_nativeSmoothHeaderScrollEnabled ? 0 : _pagerTopLogicalTarget);
|
|
4131
|
+
[_alignedBodyKeys addObject:_pagerTopPageKey];
|
|
4132
|
+
_currentLogicalOffset = logical;
|
|
4133
|
+
_headerOffset = _pagerTopLogicalTarget;
|
|
4134
|
+
[self applyHeaderOffset];
|
|
4135
|
+
[self offsetDiag:[NSString stringWithFormat:@"pager-top-complete-token=%lu-target=%.4f", (unsigned long)_pagerTopToken, _pagerTopLogicalTarget] page:_currentIndex scroll:scrollView];
|
|
4136
|
+
[self cancelPagerTop];
|
|
4137
|
+
}
|
|
4138
|
+
|
|
4139
|
+
- (void)scrollToTop:(NSInteger)target animated:(BOOL)animated
|
|
4140
|
+
{
|
|
4141
|
+
UIScrollView *scrollView = _observedScrollView;
|
|
4142
|
+
NSString *key = _observedPageKey;
|
|
4143
|
+
if ((target != 0 && target != 1) || _isBeingRecycled || _transitioning || _isPagerDragging ||
|
|
4144
|
+
_transitionPageOffsets != nil || _syntheticPageRestore || scrollView == nil || scrollView.window == nil ||
|
|
4145
|
+
key == nil || ![key isEqualToString:self.currentPageKey] || _observedPageIndex != _currentIndex ||
|
|
4146
|
+
_observedPageGeneration != _generation || self.window == nil) return;
|
|
4147
|
+
[self cancelPagerTop];
|
|
4148
|
+
// Old List phase2 notifications must run before the new target owns this page.
|
|
4149
|
+
[NSNotificationCenter.defaultCenter postNotificationName:@"OneKeyNativeListCancelScrollCommand" object:scrollView];
|
|
4150
|
+
if ([scrollView.superview isKindOfClass:RNCNativeScrollerComponentView.class]) {
|
|
4151
|
+
[(RNCNativeScrollerComponentView *)scrollView.superview stopScrolling];
|
|
4152
|
+
} else {
|
|
4153
|
+
[scrollView setContentOffset:scrollView.contentOffset animated:NO];
|
|
4154
|
+
}
|
|
4155
|
+
[_pendingPageRestoreKeys removeObject:key];
|
|
4156
|
+
[_alignedBodyKeys removeObject:key];
|
|
4157
|
+
[_suspendedBodyKeys removeObject:key];
|
|
4158
|
+
[_displayBodyOverrides removeObjectForKey:key];
|
|
4159
|
+
CGFloat logicalTarget = target == 1 ? _headerHeight : 0;
|
|
4160
|
+
_pageOffsets[key] = @(_nativeSmoothHeaderScrollEnabled ? 0 : logicalTarget);
|
|
4161
|
+
_pagerTopScrollView = scrollView;
|
|
4162
|
+
_pagerTopPageKey = [key copy];
|
|
4163
|
+
_pagerTopPageIndex = _currentIndex;
|
|
4164
|
+
_pagerTopGeneration = _generation;
|
|
4165
|
+
_pagerTopLogicalTarget = logicalTarget;
|
|
4166
|
+
_pagerTopToken++;
|
|
4167
|
+
[_commandBodyKeys addObject:key];
|
|
4168
|
+
_headerOffset = logicalTarget;
|
|
4169
|
+
[self applyHeaderOffset];
|
|
4170
|
+
CGFloat physicalTarget = RNCLimitRestoredScrollOffset(logicalTarget - scrollView.contentInset.top,
|
|
4171
|
+
scrollView.contentSize.height, scrollView.bounds.size.height, scrollView.contentInset.top, scrollView.contentInset.bottom);
|
|
4172
|
+
[self offsetDiag:[NSString stringWithFormat:@"pager-top-begin-token=%lu-target=%ld-animated=%d", (unsigned long)_pagerTopToken, (long)target, animated] page:_currentIndex scroll:scrollView];
|
|
4173
|
+
_dispatchingPagerTop = YES;
|
|
4174
|
+
[scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, physicalTarget) animated:animated];
|
|
4175
|
+
_dispatchingPagerTop = NO;
|
|
4176
|
+
[self finishPagerTopIfReached];
|
|
4177
|
+
}
|
|
4178
|
+
|
|
3966
4179
|
- (void)setPage:(NSInteger)index
|
|
3967
4180
|
{
|
|
3968
4181
|
[self goTo:index animated:YES];
|