@onekeyfe/react-native-pager-view 3.0.173 → 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 +737 -25
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +12 -0
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerView.kt +16 -0
- package/android/src/main/res/values/native_scroll_coordinator_ids.xml +2 -0
- package/android/src/test/java/com/reactnativepagerview/NativeScrollerPendingRestoreTest.kt +11 -0
- package/docs/SPEC.md +56 -1
- package/ios/RNCCollapsiblePagerViewComponentView.mm +492 -29
- package/ios/RNCNativeScrollerComponentView.h +1 -0
- package/ios/RNCNativeScrollerComponentView.mm +48 -0
- package/ios/tests/RNCCollapsiblePagerFirstFrameTests.mm +293 -0
- 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
|
@@ -43,6 +43,7 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
|
|
|
43
43
|
)
|
|
44
44
|
host.pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
|
45
45
|
override fun onPageScrolled(position: Int, offset: Float, offsetPixels: Int) {
|
|
46
|
+
host.onPagerScrolled(position, offset)
|
|
46
47
|
dispatch(reactContext, host, PageScrollEvent(host.id, position, offset))
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -55,6 +56,7 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
override fun onPageScrollStateChanged(state: Int) {
|
|
59
|
+
host.onPagerScrollStateChanged(state)
|
|
58
60
|
val value = when (state) {
|
|
59
61
|
ViewPager2.SCROLL_STATE_IDLE -> "idle"
|
|
60
62
|
ViewPager2.SCROLL_STATE_DRAGGING -> "dragging"
|
|
@@ -322,15 +324,25 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
|
|
|
322
324
|
delegate.receiveCommand(root, commandId, args)
|
|
323
325
|
}
|
|
324
326
|
|
|
327
|
+
override fun scrollToTop(view: CollapsiblePagerHost?, target: Int, animated: Boolean) {
|
|
328
|
+
view?.scrollToTop(target, animated)
|
|
329
|
+
}
|
|
330
|
+
|
|
325
331
|
override fun setPage(view: CollapsiblePagerHost?, selectedPage: Int) {
|
|
326
332
|
if (view != null && selectedPage in 0 until view.adapter.itemCount) {
|
|
333
|
+
view.beginPageTransition(selectedPage)
|
|
327
334
|
view.pager.setCurrentItem(selectedPage, true)
|
|
335
|
+
if (view.pager.scrollState == ViewPager2.SCROLL_STATE_IDLE) {
|
|
336
|
+
view.onPagerScrollStateChanged(ViewPager2.SCROLL_STATE_IDLE)
|
|
337
|
+
}
|
|
328
338
|
}
|
|
329
339
|
}
|
|
330
340
|
|
|
331
341
|
override fun setPageWithoutAnimation(view: CollapsiblePagerHost?, selectedPage: Int) {
|
|
332
342
|
if (view != null && selectedPage in 0 until view.adapter.itemCount) {
|
|
343
|
+
view.beginPageTransition(selectedPage)
|
|
333
344
|
view.pager.setCurrentItem(selectedPage, false)
|
|
345
|
+
view.onPagerScrollStateChanged(ViewPager2.SCROLL_STATE_IDLE)
|
|
334
346
|
}
|
|
335
347
|
}
|
|
336
348
|
|
|
@@ -255,6 +255,8 @@ class NativeScrollerView(context: Context) : FrameLayout(context) {
|
|
|
255
255
|
|
|
256
256
|
internal fun cancelPendingScrollRestore() = pendingRestore.cancel()
|
|
257
257
|
|
|
258
|
+
internal fun hasPendingScrollRestore(): Boolean = pendingRestore.target != null
|
|
259
|
+
|
|
258
260
|
internal fun setRefreshOffset(value: Int) {
|
|
259
261
|
refreshOffset = value
|
|
260
262
|
applyRefreshOffset()
|
|
@@ -293,11 +295,22 @@ class NativeScrollerView(context: Context) : FrameLayout(context) {
|
|
|
293
295
|
}
|
|
294
296
|
|
|
295
297
|
internal fun scrollToPosition(x: Int, y: Int, animated: Boolean) {
|
|
298
|
+
notifyScrollCommand(0, y <= 0)
|
|
296
299
|
viewport.stopMotion()
|
|
297
300
|
pendingRestore.cancel()
|
|
301
|
+
notifyScrollCommand(1, y <= 0)
|
|
298
302
|
if (animated) viewport.scrollToAnimated(y)
|
|
299
303
|
else viewport.scrollTo(0, y.coerceAtLeast(0))
|
|
300
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
|
+
}
|
|
301
314
|
}
|
|
302
315
|
|
|
303
316
|
internal fun scrollToEnd(animated: Boolean) = scrollToPosition(
|
|
@@ -587,6 +600,8 @@ internal class NativeScrollerViewport(context: Context, internal val host: Nativ
|
|
|
587
600
|
super.fling(velocityY)
|
|
588
601
|
}
|
|
589
602
|
|
|
603
|
+
internal fun isReadingMotionActive() = dragging || momentum
|
|
604
|
+
|
|
590
605
|
internal fun scrollToAnimated(y: Int) {
|
|
591
606
|
val child = getChildAt(0) ?: return
|
|
592
607
|
val margins = child.layoutParams as FrameLayout.LayoutParams
|
|
@@ -637,6 +652,7 @@ internal class NativeScrollerViewport(context: Context, internal val host: Nativ
|
|
|
637
652
|
private fun finishMomentum() {
|
|
638
653
|
if (!momentum) return
|
|
639
654
|
momentum = false
|
|
655
|
+
host.notifyScrollCommand(2)
|
|
640
656
|
host.emitScroll(force = true)
|
|
641
657
|
host.emitLifecycle("topMomentumScrollEnd")
|
|
642
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>
|
|
@@ -27,5 +27,16 @@ fun main() {
|
|
|
27
27
|
restore.cancel()
|
|
28
28
|
check(restore.target == null)
|
|
29
29
|
check(restore.anchor(120) == 120)
|
|
30
|
+
// Cancellation clears the old target without requiring the reached offset to change.
|
|
31
|
+
restore.request(target = 640, reached = 120)
|
|
32
|
+
check(restore.anchor(120) == 640)
|
|
33
|
+
restore.cancel()
|
|
34
|
+
check(restore.target == null)
|
|
35
|
+
check(restore.anchor(120) == 120)
|
|
36
|
+
// A fresh request owns its target after cancellation.
|
|
37
|
+
restore.request(target = 320, reached = 120)
|
|
38
|
+
check(restore.target == 320)
|
|
39
|
+
restore.settle(reached = 320)
|
|
40
|
+
check(restore.target == null)
|
|
30
41
|
println("Native scroller pending restore: clamp retry, partial growth, settle and cancel passed")
|
|
31
42
|
}
|
package/docs/SPEC.md
CHANGED
|
@@ -3,6 +3,60 @@
|
|
|
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 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.
|
|
59
|
+
|
|
6
60
|
## Independent NativeScroller migration
|
|
7
61
|
|
|
8
62
|
Status: implemented in source. Both native builds pass. Android focused emulator
|
|
@@ -454,7 +508,8 @@ When restoring a retained page's cached vertical offset, the pager limits only
|
|
|
454
508
|
the upper bound to the current content height, viewport and applied insets. A
|
|
455
509
|
cache captured before rows were removed MUST NOT restore an offset below the new
|
|
456
510
|
content bottom, including when removal occurs during a page transition. Valid
|
|
457
|
-
deep offsets and
|
|
511
|
+
deep offsets and pull-overscroll behavior are preserved; smooth-header selection
|
|
512
|
+
follows the shared-header and per-page body-memory contract above.
|
|
458
513
|
This check runs only on explicit restoration, not on scroll frames; UIKit pull
|
|
459
514
|
overscroll and refresh settlement retain their existing ownership. An unmeasured
|
|
460
515
|
zero-height viewport defers this upper-bound limit to a later restoration.
|