@onekeyfe/react-native-pager-view 3.0.113 → 3.0.114

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/README.md CHANGED
@@ -27,45 +27,5 @@ development and delivery stable.
27
27
  - If you are looking for original behavior and full documentation, please refer
28
28
  to the upstream repository.
29
29
 
30
- ## Collapsible pager
31
-
32
- `CollapsiblePagerView` is an opt-in container. The default `PagerView` export
33
- keeps its existing page lifetime and native implementation.
34
-
35
- ```tsx
36
- <CollapsiblePagerView
37
- header={<Header />}
38
- stickyHeader={<Tabs />}
39
- headerHeight={measuredHeaderHeight}
40
- stickyHeaderHeight={measuredTabsHeight}
41
- pageRetentionDistance={1}
42
- onMountedPagesChanged={({ mountedPages }) => {
43
- // Selected page plus one neighbour on each side by default.
44
- }}
45
- onCollapsibleStateChanged={({ nativeEvent }) => {
46
- // Settled diagnostics: headerOffset, native/attached page counts, etc.
47
- }}
48
- >
49
- {pages.map((page) => (
50
- <View key={page.key}>{page.content}</View>
51
- ))}
52
- </CollapsiblePagerView>
53
- ```
54
-
55
- Page keys must remain stable. The selected page and configured neighbours stay
56
- mounted for preheating; distant page slots remain in the pager while their
57
- React/native heavy subtrees are unmounted. iOS and Android retain a per-key
58
- scroll offset and preserve the shared header collapse when pages change. A
59
- NativeList can additionally restore its own stable item-key anchor when it is
60
- remounted; the pager does not replace that list-level anchor protocol or its
61
- cell reuse.
62
-
63
- On iOS the component observes the current `UIScrollView` content offset without
64
- replacing its delegate. Android coordinates nested scroll with the active
65
- `RecyclerView`. Web uses the active NativeList viewport automatically; another
66
- Web scroll child can opt in by exposing a DOM element with
67
- `data-collapsible-pager-scroll`. CSS scroll timelines drive header/sticky
68
- movement, so React is not updated on each vertical scroll frame.
69
-
70
30
  Thank you again to Callstack and everyone who contributes to
71
31
  `react-native-pager-view` 💙
@@ -12,6 +12,6 @@ class PagerViewPackage : ReactPackage {
12
12
  }
13
13
 
14
14
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
15
- return listOf(PagerViewViewManager(), CollapsiblePagerViewManager())
15
+ return listOf(PagerViewViewManager())
16
16
  }
17
17
  }
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import { PagerView } from "./PagerView";
3
+ import { PagerView } from "./PagerView.js";
4
4
  export default PagerView;
5
5
  export * from "./usePagerView.js";
6
- export * from "./CollapsiblePagerView";
7
6
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import { PagerView } from './PagerView';
3
+ import { PagerView } from "./PagerView.js";
4
4
  import { Animated } from 'react-native';
5
5
  import { useCallback, useMemo, useRef, useState } from 'react';
6
6
  const AnimatedPagerView = Animated.createAnimatedComponent(PagerView);
@@ -1,9 +1,8 @@
1
- import type * as ReactNative from "react-native";
2
- import { PagerView } from "./PagerView";
1
+ import type * as ReactNative from 'react-native';
2
+ import { PagerView } from './PagerView';
3
3
  export default PagerView;
4
- export * from "./usePagerView";
5
- export * from "./CollapsiblePagerView";
6
- import type { OnPageScrollEventData as PagerViewOnPageScrollEventData, OnPageSelectedEventData as PagerViewOnPageSelectedEventData, OnPageScrollStateChangedEventData as PageScrollStateChangedNativeEventData, NativeProps } from "./PagerViewNativeComponent";
4
+ export * from './usePagerView';
5
+ import type { OnPageScrollEventData as PagerViewOnPageScrollEventData, OnPageSelectedEventData as PagerViewOnPageSelectedEventData, OnPageScrollStateChangedEventData as PageScrollStateChangedNativeEventData, NativeProps } from './PagerViewNativeComponent';
7
6
  export type { PagerViewOnPageScrollEventData, PagerViewOnPageSelectedEventData, PageScrollStateChangedNativeEventData, NativeProps as PagerViewProps, };
8
7
  export type PagerViewOnPageScrollEvent = ReactNative.NativeSyntheticEvent<PagerViewOnPageScrollEventData>;
9
8
  export type PagerViewOnPageSelectedEvent = ReactNative.NativeSyntheticEvent<PagerViewOnPageSelectedEventData>;
package/package.json CHANGED
@@ -1,17 +1,15 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-pager-view",
3
- "version": "3.0.113",
3
+ "version": "3.0.114",
4
4
  "description": "React Native wrapper for Android and iOS ViewPager",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/module/index.js",
7
- "browser": "./lib/module/index.web.js",
8
7
  "types": "./lib/typescript/src/index.d.ts",
9
8
  "sideEffects": false,
10
9
  "exports": {
11
10
  ".": {
12
11
  "source": "./src/index.tsx",
13
12
  "types": "./lib/typescript/src/index.d.ts",
14
- "browser": "./lib/module/index.web.js",
15
13
  "default": "./lib/module/index.js"
16
14
  },
17
15
  "./package.json": "./package.json"
@@ -97,8 +95,7 @@
97
95
  },
98
96
  "ios": {
99
97
  "componentProvider": {
100
- "RNCViewPager": "RNCPagerViewComponentView",
101
- "RNCCollapsiblePagerView": "RNCCollapsiblePagerViewComponentView"
98
+ "RNCViewPager": "RNCPagerViewComponentView"
102
99
  }
103
100
  }
104
101
  }
package/src/index.tsx CHANGED
@@ -1,15 +1,14 @@
1
- import type * as ReactNative from "react-native";
2
- import { PagerView } from "./PagerView";
1
+ import type * as ReactNative from 'react-native';
2
+ import { PagerView } from './PagerView';
3
3
  export default PagerView;
4
- export * from "./usePagerView";
5
- export * from "./CollapsiblePagerView";
4
+ export * from './usePagerView';
6
5
 
7
6
  import type {
8
7
  OnPageScrollEventData as PagerViewOnPageScrollEventData,
9
8
  OnPageSelectedEventData as PagerViewOnPageSelectedEventData,
10
9
  OnPageScrollStateChangedEventData as PageScrollStateChangedNativeEventData,
11
10
  NativeProps,
12
- } from "./PagerViewNativeComponent";
11
+ } from './PagerViewNativeComponent';
13
12
 
14
13
  export type {
15
14
  PagerViewOnPageScrollEventData,
@@ -1,503 +0,0 @@
1
- package com.reactnativepagerview
2
-
3
- import android.content.Context
4
- import android.graphics.Rect
5
- import android.view.View
6
- import android.view.ViewGroup
7
- import android.view.ViewTreeObserver
8
- import android.widget.FrameLayout
9
- import androidx.core.view.NestedScrollingParent3
10
- import androidx.core.view.NestedScrollingParentHelper
11
- import androidx.core.view.ViewCompat
12
- import androidx.recyclerview.widget.LinearLayoutManager
13
- import androidx.recyclerview.widget.RecyclerView
14
- import androidx.viewpager2.widget.ViewPager2
15
- import java.util.WeakHashMap
16
- import kotlin.math.max
17
- import kotlin.math.min
18
-
19
- internal class CollapsiblePagerAdapter : RecyclerView.Adapter<ViewPagerViewHolder>() {
20
- private val pages = ArrayList<View>()
21
-
22
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
23
- ViewPagerViewHolder.create(parent)
24
-
25
- override fun onBindViewHolder(holder: ViewPagerViewHolder, position: Int) {
26
- val page = pages[position]
27
- val container = holder.container
28
- container.removeAllViews()
29
- (page.parent as? ViewGroup)?.removeView(page)
30
- container.addView(page)
31
- }
32
-
33
- override fun onViewRecycled(holder: ViewPagerViewHolder) {
34
- holder.container.removeAllViews()
35
- super.onViewRecycled(holder)
36
- }
37
-
38
- override fun getItemCount() = pages.size
39
-
40
- fun addPage(page: View, index: Int) {
41
- val safeIndex = index.coerceIn(0, pages.size)
42
- pages.add(safeIndex, page)
43
- notifyItemInserted(safeIndex)
44
- }
45
-
46
- fun removePage(page: View) {
47
- val index = pages.indexOf(page)
48
- if (index >= 0) {
49
- pages.removeAt(index)
50
- notifyItemRemoved(index)
51
- }
52
- }
53
-
54
- fun pageAt(index: Int) = pages[index]
55
-
56
- fun clear() {
57
- val count = pages.size
58
- pages.forEach { page -> (page.parent as? ViewGroup)?.removeView(page) }
59
- pages.clear()
60
- if (count > 0) notifyItemRangeRemoved(0, count)
61
- }
62
- }
63
-
64
- /**
65
- * Native vertical coordinator for the optional collapsible PagerView variant.
66
- * It consumes only the header part of vertical nested scroll. The active page's
67
- * vertical scroll view remains the content scroll source and horizontal gestures
68
- * remain owned by ViewPager2.
69
- */
70
- class CollapsiblePagerHost(context: Context) : FrameLayout(context), NestedScrollingParent3 {
71
- private data class RecyclerPadding(
72
- val left: Int,
73
- val top: Int,
74
- val right: Int,
75
- val bottom: Int,
76
- val clipToPadding: Boolean,
77
- )
78
-
79
- val pager = ViewPager2(context)
80
- internal val adapter = CollapsiblePagerAdapter()
81
- private val logicalChildren = ArrayList<View>()
82
- private val nestedScrollingParentHelper = NestedScrollingParentHelper(this)
83
- private val originalRecyclerPadding = WeakHashMap<RecyclerView, RecyclerPadding>()
84
- private val restoredRecyclerKeys = WeakHashMap<RecyclerView, String>()
85
- private val pageOffsets = HashMap<String, Int>()
86
- private var observedRecyclerView: RecyclerView? = null
87
- private var observedScrollListener: RecyclerView.OnScrollListener? = null
88
- private var headerView: View? = null
89
- private var stickyHeaderView: View? = null
90
- private val pageContentLayoutListener = ViewTreeObserver.OnPreDrawListener {
91
- // Fabric can mount a retained list without another Android layout pass.
92
- // Apply its header insets before that list first draws.
93
- prepareAdjacentPages()
94
- attachRecyclerObserver()
95
- true
96
- }
97
-
98
- var selectedPage = 0
99
- private set
100
- var pendingInitialPage = 0
101
- var headerHeightPx = 0
102
- set(value) {
103
- if (field == value) return
104
- field = max(0, value)
105
- headerOffsetPx = min(headerOffsetPx, field)
106
- reapplyRecyclerInsets()
107
- requestLayout()
108
- }
109
- var stickyHeaderHeightPx = 0
110
- set(value) {
111
- if (field == value) return
112
- field = max(0, value)
113
- reapplyRecyclerInsets()
114
- requestLayout()
115
- }
116
- var headerOffsetPx = 0
117
- private set
118
- var pageKeys: List<String> = emptyList()
119
- var retainedPages: String = "[]"
120
- var onHeaderOffsetChanged: (() -> Unit)? = null
121
-
122
- init {
123
- isSaveEnabled = false
124
- clipChildren = true
125
- pager.id = View.generateViewId()
126
- pager.adapter = adapter
127
- pager.isSaveEnabled = false
128
- super.addView(
129
- pager,
130
- LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT),
131
- )
132
- }
133
-
134
- fun addReactChild(child: View, index: Int) {
135
- val safeIndex = index.coerceIn(0, logicalChildren.size)
136
- logicalChildren.add(safeIndex, child)
137
- when (safeIndex) {
138
- 0 -> {
139
- headerView = child
140
- (child.parent as? ViewGroup)?.removeView(child)
141
- super.addView(child)
142
- }
143
- 1 -> {
144
- stickyHeaderView = child
145
- (child.parent as? ViewGroup)?.removeView(child)
146
- super.addView(child)
147
- }
148
- else -> adapter.addPage(child, safeIndex - PAGE_SLOT_OFFSET)
149
- }
150
- applyPendingInitialPage()
151
- headerView?.bringToFront()
152
- stickyHeaderView?.bringToFront()
153
- requestLayout()
154
- }
155
-
156
- fun removeReactChild(child: View) {
157
- val index = logicalChildren.indexOf(child)
158
- if (index < 0) return
159
- logicalChildren.removeAt(index)
160
- when (index) {
161
- 0 -> {
162
- super.removeView(child)
163
- headerView = null
164
- }
165
- 1 -> {
166
- super.removeView(child)
167
- stickyHeaderView = null
168
- }
169
- else -> {
170
- findVerticalRecyclerView(child)?.let(::restoreRecyclerInsets)
171
- adapter.removePage(child)
172
- }
173
- }
174
- }
175
-
176
- fun removeAllReactChildren() {
177
- detachRecyclerObserver()
178
- for (recycler in originalRecyclerPadding.keys.toList()) {
179
- restoreRecyclerInsets(recycler)
180
- }
181
- headerView?.let { view -> super.removeView(view) }
182
- stickyHeaderView?.let { view -> super.removeView(view) }
183
- headerView = null
184
- stickyHeaderView = null
185
- logicalChildren.clear()
186
- adapter.clear()
187
- }
188
-
189
- fun reactChildCount() = logicalChildren.size
190
-
191
- fun reactChildAt(index: Int) = logicalChildren[index]
192
-
193
- fun selectPage(position: Int) {
194
- if (adapter.itemCount == 0) return
195
- detachRecyclerObserver()
196
- selectedPage = position.coerceIn(0, adapter.itemCount - 1)
197
- post {
198
- prepareAdjacentPages()
199
- attachRecyclerObserver()
200
- }
201
- }
202
-
203
- fun applyPendingInitialPage() {
204
- if (pendingInitialPage !in 0 until adapter.itemCount) return
205
- if (pager.currentItem != pendingInitialPage) {
206
- pager.setCurrentItem(pendingInitialPage, false)
207
- }
208
- selectPage(pendingInitialPage)
209
- }
210
-
211
- fun attachedPageCount(): Int = (pager.getChildAt(0) as? RecyclerView)?.childCount ?: 0
212
-
213
- fun observedScrollableCount(): Int = originalRecyclerPadding.size
214
-
215
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
216
- val width = MeasureSpec.getSize(widthMeasureSpec)
217
- val height = MeasureSpec.getSize(heightMeasureSpec)
218
- val pagerHeight = height + headerHeightPx
219
- pager.measure(
220
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
221
- MeasureSpec.makeMeasureSpec(pagerHeight, MeasureSpec.EXACTLY),
222
- )
223
- headerView?.measure(
224
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
225
- MeasureSpec.makeMeasureSpec(headerHeightPx, MeasureSpec.EXACTLY),
226
- )
227
- stickyHeaderView?.measure(
228
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
229
- MeasureSpec.makeMeasureSpec(stickyHeaderHeightPx, MeasureSpec.EXACTLY),
230
- )
231
- setMeasuredDimension(width, height)
232
- }
233
-
234
- override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
235
- val width = right - left
236
- val height = bottom - top
237
- // RN ancestors allow overflow; keep translated header content inside this viewport.
238
- clipBounds = Rect(0, 0, width, height)
239
- pager.layout(0, 0, width, height + headerHeightPx)
240
- headerView?.layout(0, 0, width, headerHeightPx)
241
- stickyHeaderView?.layout(
242
- 0,
243
- headerHeightPx,
244
- width,
245
- headerHeightPx + stickyHeaderHeightPx,
246
- )
247
- applyHeaderOffset()
248
- post {
249
- prepareAdjacentPages()
250
- attachRecyclerObserver()
251
- }
252
- }
253
-
254
- private fun setHeaderOffset(offset: Int) {
255
- val next = offset.coerceIn(0, headerHeightPx)
256
- if (headerOffsetPx == next) return
257
- headerOffsetPx = next
258
- applyHeaderOffset()
259
- }
260
-
261
- private fun applyHeaderOffset() {
262
- val offset = headerOffsetPx.toFloat()
263
- pager.translationY = -offset
264
- headerView?.translationY = -offset
265
- stickyHeaderView?.translationY = -offset
266
- }
267
-
268
- private fun pageKey(index: Int): String = pageKeys.getOrNull(index) ?: "page-$index"
269
-
270
- private fun currentPageKey(): String = pageKey(selectedPage)
271
-
272
- private fun isDescendant(view: View, ancestor: View): Boolean {
273
- var current: View? = view
274
- while (current != null) {
275
- if (current === ancestor) return true
276
- current = current.parent as? View
277
- }
278
- return false
279
- }
280
-
281
- private fun findVerticalRecyclerView(view: View): RecyclerView? {
282
- if (view is RecyclerView) {
283
- val manager = view.layoutManager
284
- if (manager !is LinearLayoutManager || manager.orientation == RecyclerView.VERTICAL) {
285
- return view
286
- }
287
- }
288
- if (view is ViewGroup) {
289
- for (index in 0 until view.childCount) {
290
- findVerticalRecyclerView(view.getChildAt(index))?.let { return it }
291
- }
292
- }
293
- return null
294
- }
295
-
296
- private fun recyclerViewForPage(index: Int): RecyclerView? {
297
- if (index !in 0 until adapter.itemCount) return null
298
- return findVerticalRecyclerView(adapter.pageAt(index))
299
- }
300
-
301
- private fun prepareAdjacentPages() {
302
- val first = max(0, selectedPage - 1)
303
- val last = min(adapter.itemCount - 1, selectedPage + 1)
304
- for (index in first..last) {
305
- recyclerViewForPage(index)?.let { recycler ->
306
- applyRecyclerInsets(recycler, index)
307
- }
308
- }
309
- }
310
-
311
- private fun attachRecyclerObserver() {
312
- if (selectedPage !in 0 until adapter.itemCount) return
313
- val previous = observedRecyclerView
314
- if (previous != null && !isDescendant(previous, adapter.pageAt(selectedPage))) {
315
- detachRecyclerObserver()
316
- // A replacement list starts at its first row, retaining only header collapse.
317
- pageOffsets[currentPageKey()] = 0
318
- }
319
- val recycler = recyclerViewForPage(selectedPage) ?: return
320
- if (observedRecyclerView === recycler) {
321
- applyRecyclerInsets(recycler, selectedPage)
322
- return
323
- }
324
-
325
- detachRecyclerObserver()
326
- observedRecyclerView = recycler
327
- applyRecyclerInsets(recycler, selectedPage)
328
- val listener = object : RecyclerView.OnScrollListener() {
329
- override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
330
- pageOffsets[currentPageKey()] = recyclerView.computeVerticalScrollOffset()
331
- }
332
- }
333
- observedScrollListener = listener
334
- recycler.addOnScrollListener(listener)
335
-
336
- }
337
-
338
- private fun detachRecyclerObserver() {
339
- storeObservedPageOffset()
340
- val recycler = observedRecyclerView
341
- val listener = observedScrollListener
342
- if (recycler != null && listener != null) recycler.removeOnScrollListener(listener)
343
- observedRecyclerView = null
344
- observedScrollListener = null
345
- }
346
-
347
- private fun storeObservedPageOffset() {
348
- observedRecyclerView?.let { recycler ->
349
- pageOffsets[currentPageKey()] = recycler.computeVerticalScrollOffset()
350
- }
351
- }
352
-
353
- private fun applyRecyclerInsets(recycler: RecyclerView, pageIndex: Int) {
354
- val original = originalRecyclerPadding.getOrPut(recycler) {
355
- RecyclerPadding(
356
- recycler.paddingLeft,
357
- recycler.paddingTop,
358
- recycler.paddingRight,
359
- recycler.paddingBottom,
360
- recycler.clipToPadding,
361
- )
362
- }
363
- val topInset = headerHeightPx + stickyHeaderHeightPx
364
- recycler.clipToPadding = false
365
- val top = original.top + topInset
366
- // The taller pager already accounts for the translated header. Adding it
367
- // again leaves a full header-sized blank footer at the end of long lists.
368
- val bottom = original.bottom
369
- if (recycler.paddingLeft != original.left || recycler.paddingTop != top ||
370
- recycler.paddingRight != original.right || recycler.paddingBottom != bottom) {
371
- recycler.setPadding(original.left, top, original.right, bottom)
372
- }
373
- val key = pageKey(pageIndex)
374
- if (restoredRecyclerKeys[recycler] != key) {
375
- restoredRecyclerKeys[recycler] = key
376
- recycler.post {
377
- if (restoredRecyclerKeys[recycler] != key) return@post
378
- val saved = pageOffsets[key] ?: 0
379
- val current = recycler.computeVerticalScrollOffset()
380
- if (saved != current) recycler.scrollBy(0, saved - current)
381
- }
382
- }
383
- }
384
-
385
- private fun reapplyRecyclerInsets() {
386
- prepareAdjacentPages()
387
- }
388
-
389
- private fun restoreRecyclerInsets(recycler: RecyclerView) {
390
- val original = originalRecyclerPadding.remove(recycler) ?: return
391
- restoredRecyclerKeys.remove(recycler)
392
- recycler.clipToPadding = original.clipToPadding
393
- recycler.setPadding(original.left, original.top, original.right, original.bottom)
394
- }
395
-
396
- private fun isCurrentPageTarget(target: View): Boolean {
397
- if (selectedPage !in 0 until adapter.itemCount) return false
398
- return isDescendant(target, adapter.pageAt(selectedPage))
399
- }
400
-
401
- // RN ScrollView uses the platform nested-scroll callbacks; RecyclerView
402
- // uses the AndroidX variants with an explicit input type.
403
- override fun onStartNestedScroll(child: View, target: View, axes: Int): Boolean =
404
- onStartNestedScroll(child, target, axes, ViewCompat.TYPE_TOUCH)
405
-
406
- override fun onNestedScrollAccepted(child: View, target: View, axes: Int) =
407
- onNestedScrollAccepted(child, target, axes, ViewCompat.TYPE_TOUCH)
408
-
409
- override fun onStopNestedScroll(target: View) =
410
- onStopNestedScroll(target, ViewCompat.TYPE_TOUCH)
411
-
412
- override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray) =
413
- onNestedPreScroll(target, dx, dy, consumed, ViewCompat.TYPE_TOUCH)
414
-
415
- override fun onNestedScroll(
416
- target: View,
417
- dxConsumed: Int,
418
- dyConsumed: Int,
419
- dxUnconsumed: Int,
420
- dyUnconsumed: Int,
421
- ) = onNestedScroll(
422
- target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, ViewCompat.TYPE_TOUCH,
423
- )
424
-
425
- override fun onStartNestedScroll(child: View, target: View, axes: Int, type: Int): Boolean =
426
- axes and ViewCompat.SCROLL_AXIS_VERTICAL != 0 && isCurrentPageTarget(target)
427
-
428
- override fun onNestedScrollAccepted(child: View, target: View, axes: Int, type: Int) {
429
- nestedScrollingParentHelper.onNestedScrollAccepted(child, target, axes, type)
430
- }
431
-
432
- override fun onStopNestedScroll(target: View, type: Int) {
433
- nestedScrollingParentHelper.onStopNestedScroll(target, type)
434
- onHeaderOffsetChanged?.invoke()
435
- }
436
-
437
- override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray, type: Int) {
438
- if (!isCurrentPageTarget(target)) return
439
- if (dy > 0 && headerOffsetPx < headerHeightPx) {
440
- val used = min(dy, headerHeightPx - headerOffsetPx)
441
- setHeaderOffset(headerOffsetPx + used)
442
- consumed[1] += used
443
- } else if (dy < 0 && headerOffsetPx > 0 && !target.canScrollVertically(-1)) {
444
- val used = max(dy, -headerOffsetPx)
445
- setHeaderOffset(headerOffsetPx + used)
446
- consumed[1] += used
447
- }
448
- }
449
-
450
- override fun onNestedScroll(
451
- target: View,
452
- dxConsumed: Int,
453
- dyConsumed: Int,
454
- dxUnconsumed: Int,
455
- dyUnconsumed: Int,
456
- type: Int,
457
- consumed: IntArray,
458
- ) {
459
- if (!isCurrentPageTarget(target) || dyUnconsumed >= 0 || headerOffsetPx <= 0) return
460
- val used = max(dyUnconsumed, -headerOffsetPx)
461
- setHeaderOffset(headerOffsetPx + used)
462
- consumed[1] += used
463
- }
464
-
465
- override fun onNestedScroll(
466
- target: View,
467
- dxConsumed: Int,
468
- dyConsumed: Int,
469
- dxUnconsumed: Int,
470
- dyUnconsumed: Int,
471
- type: Int,
472
- ) {
473
- onNestedScroll(
474
- target,
475
- dxConsumed,
476
- dyConsumed,
477
- dxUnconsumed,
478
- dyUnconsumed,
479
- type,
480
- IntArray(2),
481
- )
482
- }
483
-
484
- override fun getNestedScrollAxes() = nestedScrollingParentHelper.nestedScrollAxes
485
-
486
- override fun onAttachedToWindow() {
487
- super.onAttachedToWindow()
488
- viewTreeObserver.addOnPreDrawListener(pageContentLayoutListener)
489
- }
490
-
491
- override fun onDetachedFromWindow() {
492
- viewTreeObserver.removeOnPreDrawListener(pageContentLayoutListener)
493
- detachRecyclerObserver()
494
- for (recycler in originalRecyclerPadding.keys.toList()) {
495
- restoreRecyclerInsets(recycler)
496
- }
497
- super.onDetachedFromWindow()
498
- }
499
-
500
- companion object {
501
- const val PAGE_SLOT_OFFSET = 2
502
- }
503
- }