@onekeyfe/react-native-pager-view 6.7.0-alpha.436 → 6.7.0-alpha.445
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 +16 -0
- package/android/build.gradle +1 -0
- package/android/src/androidTest/java/com/reactnativepagerview/CollapsiblePagerTabReservationTest.kt +135 -0
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +88 -12
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerNativeHeaders.kt +442 -15
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +11 -1
- package/android/src/main/java/com/reactnativepagerview/event/NativeHeaderPressEvent.kt +8 -0
- package/docs/SPEC.md +298 -3
- package/ios/RNCCollapsiblePagerViewComponentView.mm +834 -20
- package/ios/tests/RNCCollapsiblePagerFirstFrameTests.mm +61 -0
- package/ios/tests/RNCCollapsiblePagerHitTestTests.mm +22 -0
- package/lib/module/CollapsiblePagerView.js +37 -5
- package/lib/module/CollapsiblePagerView.web.js +519 -6
- package/lib/module/CollapsiblePagerViewNativeComponent.ts +6 -0
- package/lib/module/NativeScrollerNativeComponent.ts +0 -1
- package/lib/typescript/src/CollapsiblePagerView.d.ts +31 -2
- package/lib/typescript/src/CollapsiblePagerView.web.d.ts +44 -1
- package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +11 -0
- package/lib/typescript/src/NativeScroller.d.ts +2 -2
- package/package.json +3 -2
- package/src/CollapsiblePagerView.tsx +68 -5
- package/src/CollapsiblePagerView.web.tsx +464 -5
- package/src/CollapsiblePagerViewNativeComponent.ts +6 -0
- package/src/NativeScroller.tsx +2 -3
- package/src/NativeScrollerNativeComponent.ts +0 -1
package/README.md
CHANGED
|
@@ -87,6 +87,18 @@ non-adjacent presses jump directly to the target without passing intermediate
|
|
|
87
87
|
pages. Set `nativeTabPressAnimationEnabled={true}` to always animate, or `false`
|
|
88
88
|
to always jump. Swipe gestures and imperative page commands are unchanged.
|
|
89
89
|
|
|
90
|
+
The `text` variant supports `controlled`, stable `selectedKey` and one per-key
|
|
91
|
+
`toolbar` map. Controlled presses report intent; the caller keeps page commands,
|
|
92
|
+
menus and routing. Label colors follow actual page movement while selected font
|
|
93
|
+
weight follows business selection. Toolbar artwork, label, action key and selected
|
|
94
|
+
background transfer together only when the final physical page and selection
|
|
95
|
+
agree. Motion keeps the old artwork with hit/AX disabled; two present icons replace
|
|
96
|
+
in place, and only presence changes fade for about 100 ms. Omitting `toolbar`
|
|
97
|
+
reserves zero width; `{}` reserves 44 logical units, and nonempty maps use their
|
|
98
|
+
largest `contentWidth + trailingInset`. Missing/failed content keeps that slot
|
|
99
|
+
without an active control. See [the contract](docs/SPEC.md#text-tabs-controlled-selection-and-per-tab-toolbar)
|
|
100
|
+
for ownership, cancellation, progress, fallback and current acceptance limits.
|
|
101
|
+
|
|
90
102
|
> **Behavior change:** earlier versions animated every native tab press when
|
|
91
103
|
> `nativeTabPressAnimationEnabled` was omitted. Pass
|
|
92
104
|
> `nativeTabPressAnimationEnabled={true}` to keep that behavior.
|
|
@@ -142,3 +154,7 @@ position emit a momentum begin/end pair; a no-op emits no new pair. A new comman
|
|
|
142
154
|
new touch, content-root replacement or detach ends the previous active sequence.
|
|
143
155
|
The focused JS tests verify wrapper routing, not native scrolling,
|
|
144
156
|
Yoga rendering, keyboard interaction or refresh placement on a device.
|
|
157
|
+
|
|
158
|
+
The codegen type boundary uses React Native's public `CodegenTypes` namespace.
|
|
159
|
+
RN 0.86.2/0.88.0 declaration and parser checks preserve emitted JS, native schemas
|
|
160
|
+
and the existing NativeScroller method set; no private type import patch is needed.
|
package/android/build.gradle
CHANGED
|
@@ -227,6 +227,7 @@ dependencies {
|
|
|
227
227
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
228
228
|
implementation 'androidx.viewpager2:viewpager2:1.1.0'
|
|
229
229
|
implementation project(":onekeyfe_react-native-native-logger")
|
|
230
|
+
implementation project(":onekeyfe_react-native-image")
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
if (isNewArchitectureEnabled()) {
|
package/android/src/androidTest/java/com/reactnativepagerview/CollapsiblePagerTabReservationTest.kt
CHANGED
|
@@ -6,6 +6,8 @@ import android.content.pm.ApplicationInfo
|
|
|
6
6
|
import android.graphics.Bitmap
|
|
7
7
|
import android.graphics.Canvas
|
|
8
8
|
import android.graphics.Color
|
|
9
|
+
import android.graphics.drawable.ColorDrawable
|
|
10
|
+
import android.graphics.drawable.GradientDrawable
|
|
9
11
|
import android.test.InstrumentationTestCase
|
|
10
12
|
import android.view.MotionEvent
|
|
11
13
|
import android.view.View
|
|
@@ -303,4 +305,137 @@ class CollapsiblePagerTabReservationTest : InstrumentationTestCase() {
|
|
|
303
305
|
instrumentation.waitForIdleSync()
|
|
304
306
|
}
|
|
305
307
|
}
|
|
308
|
+
fun testControlledPagerSettlesWhenOnlyParentLayoutRequestRemains() {
|
|
309
|
+
val context = instrumentation.targetContext
|
|
310
|
+
val activity = instrumentation.startActivitySync(
|
|
311
|
+
Intent(context, CollapsiblePagerHitTestActivity::class.java)
|
|
312
|
+
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
|
|
313
|
+
) as CollapsiblePagerHitTestActivity
|
|
314
|
+
lateinit var host: CollapsiblePagerHost
|
|
315
|
+
lateinit var tab: CollapsiblePagerNativeTabBarView
|
|
316
|
+
val drain = CollapsiblePagerHost::class.java.getDeclaredMethod("layoutPagerIfRequested").apply { isAccessible = true }
|
|
317
|
+
try {
|
|
318
|
+
instrumentation.runOnMainSync {
|
|
319
|
+
val density = context.resources.displayMetrics.density
|
|
320
|
+
val width = (320 * density).roundToInt()
|
|
321
|
+
val height = (500 * density).roundToInt()
|
|
322
|
+
host = CollapsiblePagerHost(context)
|
|
323
|
+
host.pendingInitialPage = 1
|
|
324
|
+
activity.setContentView(host)
|
|
325
|
+
repeat(4) { host.addReactChild(View(context), it) }
|
|
326
|
+
host.applyPendingInitialPage()
|
|
327
|
+
host.nativeTabBarVariant = "text"
|
|
328
|
+
host.applyNativeHeaderStyle()
|
|
329
|
+
host.updateNativeTabBarItems("""[{"key":"a","title":"A"},{"key":"b","title":"B"}]""")
|
|
330
|
+
host.updateNativeTabBarConfig("""{"controlled":true,"selectedKey":"b","pageKeys":["a","b"],"toolbar":{}}""")
|
|
331
|
+
host.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
|
|
332
|
+
View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY))
|
|
333
|
+
host.layout(0, 0, width, height)
|
|
334
|
+
tab = (0 until host.childCount).map(host::getChildAt)
|
|
335
|
+
.filterIsInstance<CollapsiblePagerNativeTabBarView>().single()
|
|
336
|
+
host.pager.setCurrentItem(1, false)
|
|
337
|
+
val recycler = host.pager.getChildAt(0) as RecyclerView
|
|
338
|
+
host.pager.requestLayout()
|
|
339
|
+
recycler.requestLayout()
|
|
340
|
+
recycler.measure(View.MeasureSpec.makeMeasureSpec(recycler.width, View.MeasureSpec.EXACTLY),
|
|
341
|
+
View.MeasureSpec.makeMeasureSpec(recycler.height, View.MeasureSpec.EXACTLY))
|
|
342
|
+
recycler.layout(recycler.left, recycler.top, recycler.right, recycler.bottom)
|
|
343
|
+
assertFalse(recycler.isLayoutRequested)
|
|
344
|
+
assertTrue(host.pager.isLayoutRequested)
|
|
345
|
+
assertTrue(tab.needsToolbarPagerSettlement(1))
|
|
346
|
+
drain.invoke(host)
|
|
347
|
+
assertFalse(host.pager.isLayoutRequested)
|
|
348
|
+
}
|
|
349
|
+
instrumentation.waitForIdleSync()
|
|
350
|
+
instrumentation.runOnMainSync {
|
|
351
|
+
assertFalse(tab.needsToolbarPagerSettlement(1))
|
|
352
|
+
val posted = CollapsiblePagerHost::class.java.getDeclaredField("toolbarSettlePostedGeneration").apply { isAccessible = true }
|
|
353
|
+
repeat(50) { drain.invoke(host) }
|
|
354
|
+
assertNull(posted.get(host))
|
|
355
|
+
assertFalse(host.pager.isLayoutRequested)
|
|
356
|
+
}
|
|
357
|
+
instrumentation.runOnMainSync {
|
|
358
|
+
val parent = host.parent as ViewGroup
|
|
359
|
+
val index = parent.indexOfChild(host)
|
|
360
|
+
parent.removeView(host)
|
|
361
|
+
parent.addView(host, index)
|
|
362
|
+
assertTrue(host.isAttachedToWindow)
|
|
363
|
+
assertTrue(host.isShown)
|
|
364
|
+
assertTrue(host.width > 0 && host.height > 0)
|
|
365
|
+
assertFalse(host.isLaidOut)
|
|
366
|
+
assertEquals(1, host.pager.currentItem)
|
|
367
|
+
drain.invoke(host)
|
|
368
|
+
assertTrue(host.isLaidOut)
|
|
369
|
+
}
|
|
370
|
+
instrumentation.waitForIdleSync()
|
|
371
|
+
instrumentation.runOnMainSync {
|
|
372
|
+
assertEquals(1, host.pager.currentItem)
|
|
373
|
+
assertFalse(tab.needsToolbarPagerSettlement(1))
|
|
374
|
+
}
|
|
375
|
+
} finally {
|
|
376
|
+
instrumentation.runOnMainSync { activity.finish() }
|
|
377
|
+
instrumentation.waitForIdleSync()
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
fun testTextToolbarBackgroundCoversSlotWithSingleTranslucentLayer() {
|
|
382
|
+
val context = instrumentation.targetContext
|
|
383
|
+
val activity = instrumentation.startActivitySync(
|
|
384
|
+
Intent(context, CollapsiblePagerHitTestActivity::class.java)
|
|
385
|
+
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
|
|
386
|
+
) as CollapsiblePagerHitTestActivity
|
|
387
|
+
try {
|
|
388
|
+
instrumentation.runOnMainSync {
|
|
389
|
+
val density = context.resources.displayMetrics.density
|
|
390
|
+
fun dp(value: Int) = (value * density).roundToInt()
|
|
391
|
+
val width = dp(320)
|
|
392
|
+
val height = dp(44)
|
|
393
|
+
val tab = CollapsiblePagerNativeTabBarView(context)
|
|
394
|
+
tab.layoutDirection = View.LAYOUT_DIRECTION_LTR
|
|
395
|
+
activity.setContentView(tab)
|
|
396
|
+
tab.updateItemsJSON("""[{"key":"a","title":"A"}]""")
|
|
397
|
+
fun configure(variant: String, background: Int, entry: Boolean) {
|
|
398
|
+
tab.updateStyle(44.0, variant, 20.0, 0.0, 8.0, 18.0, null, 2.0, 0.0)
|
|
399
|
+
val toolbar = if (entry) """{"a":{"iconName":"SliderHorOutline"}}""" else "{}"
|
|
400
|
+
tab.updateConfigJSON("""{"controlled":true,"selectedKey":"a","pageKeys":["a"],"toolbar":$toolbar}""")
|
|
401
|
+
tab.updateToolbarPagerState(0, false)
|
|
402
|
+
tab.updateColors(background, Color.BLACK, Color.GRAY, Color.BLACK)
|
|
403
|
+
tab.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
|
|
404
|
+
View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY))
|
|
405
|
+
tab.layout(0, 0, width, height)
|
|
406
|
+
}
|
|
407
|
+
for (background in listOf(0xff204060.toInt(), 0x80204060.toInt(), Color.TRANSPARENT)) {
|
|
408
|
+
for (entry in listOf(false, true)) {
|
|
409
|
+
configure("text", background, entry)
|
|
410
|
+
val row = tab.getChildAt(0) as HorizontalScrollView
|
|
411
|
+
assertEquals(width - dp(44), row.width)
|
|
412
|
+
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
413
|
+
tab.draw(Canvas(bitmap))
|
|
414
|
+
assertEquals(Color.alpha(background), Color.alpha(bitmap.getPixel(1, height - 1)))
|
|
415
|
+
assertEquals(Color.alpha(background), Color.alpha(bitmap.getPixel(width - 1, height - 1)))
|
|
416
|
+
assertEquals(Color.TRANSPARENT, (row.background as ColorDrawable).color)
|
|
417
|
+
assertEquals(Color.TRANSPARENT, ((row.getChildAt(0) as ViewGroup).background as ColorDrawable).color)
|
|
418
|
+
bitmap.recycle()
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
for (variant in listOf("underline", "text", "segmented", "text")) {
|
|
422
|
+
val background = 0xff204060.toInt()
|
|
423
|
+
configure(variant, background, false)
|
|
424
|
+
val row = tab.getChildAt(0) as HorizontalScrollView
|
|
425
|
+
assertEquals(if (variant == "text") background else Color.TRANSPARENT,
|
|
426
|
+
(tab.background as ColorDrawable).color)
|
|
427
|
+
if (variant == "underline") assertEquals(background, (row.background as ColorDrawable).color)
|
|
428
|
+
if (variant == "segmented") {
|
|
429
|
+
val content = row.getChildAt(0) as ViewGroup
|
|
430
|
+
val track = content.getChildAt(0)
|
|
431
|
+
assertEquals(background, (track.background as GradientDrawable).color?.defaultColor)
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
} finally {
|
|
436
|
+
instrumentation.runOnMainSync { activity.finish() }
|
|
437
|
+
instrumentation.waitForIdleSync()
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
306
441
|
}
|
|
@@ -115,6 +115,16 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
115
115
|
|
|
116
116
|
val pager = ViewPager2(context)
|
|
117
117
|
internal val adapter = CollapsiblePagerAdapter()
|
|
118
|
+
var onNativeToolbarPress: ((String, DoubleArray) -> Unit)? = null
|
|
119
|
+
fun updateNativeTabBarConfig(value: String?) {
|
|
120
|
+
toolbarSettledStamp = null
|
|
121
|
+
nativeTabBarView.updateConfigJSON(value)
|
|
122
|
+
settleNativeTabProgressIfReady()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private var toolbarTransitionGeneration = 0
|
|
126
|
+
private var toolbarSettlePostedGeneration: Int? = null
|
|
127
|
+
private var toolbarSettledStamp: Pair<Int, Int>? = null
|
|
118
128
|
private val nativeTabBarView = CollapsiblePagerNativeTabBarView(context)
|
|
119
129
|
private val nativeSubHeaderView = CollapsiblePagerNativeSubHeaderView(context)
|
|
120
130
|
private val logicalChildren = ArrayList<View>()
|
|
@@ -332,6 +342,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
332
342
|
pager,
|
|
333
343
|
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT),
|
|
334
344
|
)
|
|
345
|
+
nativeTabBarView.onToolbarPress = { key, rect -> onNativeToolbarPress?.invoke(key, rect) }
|
|
335
346
|
nativeTabBarView.onItemPress = { index, key -> onNativeTabPress?.invoke(index, key) }
|
|
336
347
|
nativeSubHeaderView.onItemPress = { index, key -> onNativeSubHeaderPress?.invoke(index, key) }
|
|
337
348
|
super.addView(nativeTabBarView)
|
|
@@ -399,6 +410,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
399
410
|
}
|
|
400
411
|
|
|
401
412
|
fun updateNativeTabBarItems(value: String?) {
|
|
413
|
+
toolbarSettledStamp = null
|
|
402
414
|
nativeTabBarView.updateItemsJSON(value)
|
|
403
415
|
bringNativeHeadersToFront()
|
|
404
416
|
updateHeaderLayout()
|
|
@@ -411,10 +423,44 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
411
423
|
updateHeaderLayout()
|
|
412
424
|
}
|
|
413
425
|
|
|
414
|
-
fun updateNativeTabProgress(position: Int, offset: Float) {
|
|
426
|
+
fun updateNativeTabProgress(position: Int, offset: Float, fromActualPosition: Boolean = false) {
|
|
427
|
+
// ViewPager2 selects the target before a smooth scroll reaches it.
|
|
428
|
+
if (!fromActualPosition && nativeTabBarView.usesControlledTextProgress()) return
|
|
429
|
+
if (fromActualPosition) toolbarSettledStamp = null
|
|
415
430
|
nativeTabBarView.setProgress(position + offset)
|
|
416
431
|
}
|
|
417
432
|
|
|
433
|
+
private fun settledPagerPage(): Int? {
|
|
434
|
+
if (!isAttachedToWindow || !isLaidOut || width <= 0 || pager.width <= 0 ||
|
|
435
|
+
pager.isLayoutRequested || isPagerRecyclerLayoutSuppressed() || pager.isFakeDragging ||
|
|
436
|
+
pager.scrollState != ViewPager2.SCROLL_STATE_IDLE || pager.currentItem !in 0 until adapter.itemCount) return null
|
|
437
|
+
val recycler = pager.getChildAt(0) as? RecyclerView ?: return null
|
|
438
|
+
if (recycler.isLayoutRequested || recycler.isComputingLayout || recycler.width <= 0 || recycler.height <= 0) return null
|
|
439
|
+
return pager.currentItem
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
private fun suspendNativeToolbar() {
|
|
443
|
+
toolbarTransitionGeneration++
|
|
444
|
+
toolbarSettledStamp = null
|
|
445
|
+
nativeTabBarView.updateToolbarPagerState(-1, true)
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private fun settleNativeTabProgressIfReady() {
|
|
449
|
+
val page = settledPagerPage() ?: return
|
|
450
|
+
val generation = toolbarTransitionGeneration
|
|
451
|
+
if (toolbarSettledStamp == (generation to page) && !nativeTabBarView.needsToolbarPagerSettlement(page)) return
|
|
452
|
+
if (toolbarSettlePostedGeneration == generation) return
|
|
453
|
+
toolbarSettlePostedGeneration = generation
|
|
454
|
+
postForCurrentAttachment {
|
|
455
|
+
if (toolbarTransitionGeneration != generation || toolbarSettlePostedGeneration != generation) return@postForCurrentAttachment
|
|
456
|
+
toolbarSettlePostedGeneration = null
|
|
457
|
+
val settledPage = settledPagerPage() ?: return@postForCurrentAttachment
|
|
458
|
+
if (nativeTabBarView.usesControlledTextProgress()) updateNativeTabProgress(settledPage, 0f, fromActualPosition = true)
|
|
459
|
+
nativeTabBarView.updateToolbarPagerState(settledPage, false)
|
|
460
|
+
toolbarSettledStamp = generation to settledPage
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
418
464
|
fun logPagerState(reason: String) {
|
|
419
465
|
log(
|
|
420
466
|
"pager-state reason=$reason inner=$selectedPage outer=${outerPagerIndex()} " +
|
|
@@ -588,6 +634,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
588
634
|
}
|
|
589
635
|
|
|
590
636
|
internal fun beginPageTransition(target: Int? = null) {
|
|
637
|
+
suspendNativeToolbar()
|
|
591
638
|
cancelPagerTop()
|
|
592
639
|
if (adapter.itemCount == 0 || !nativeSmoothHeaderScrollEnabled || headerHeightPx <= 0) return
|
|
593
640
|
if (transitionHeaderOffsets == null) {
|
|
@@ -627,10 +674,12 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
627
674
|
}
|
|
628
675
|
|
|
629
676
|
internal fun onPagerScrolled(position: Int, offset: Float) {
|
|
677
|
+
val controlledTextProgress = nativeTabBarView.usesControlledTextProgress()
|
|
678
|
+
if (controlledTextProgress) updateNativeTabProgress(position, offset, fromActualPosition = true)
|
|
630
679
|
if (transitionHeaderOffsets == null) return
|
|
631
680
|
alignPageBody(position)
|
|
632
681
|
if (position + 1 < adapter.itemCount) alignPageBody(position + 1)
|
|
633
|
-
updateNativeTabProgress(position, offset)
|
|
682
|
+
if (!controlledTextProgress) updateNativeTabProgress(position, offset)
|
|
634
683
|
}
|
|
635
684
|
|
|
636
685
|
internal fun onPagerScrollStateChanged(state: Int) {
|
|
@@ -640,6 +689,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
640
689
|
} else if (state == ViewPager2.SCROLL_STATE_IDLE && transitionHeaderOffsets != null) {
|
|
641
690
|
finishPageTransition(pager.currentItem)
|
|
642
691
|
}
|
|
692
|
+
if (state == ViewPager2.SCROLL_STATE_IDLE) settleNativeTabProgressIfReady()
|
|
643
693
|
}
|
|
644
694
|
|
|
645
695
|
private fun finishPageTransition(position: Int) {
|
|
@@ -729,23 +779,44 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
729
779
|
|
|
730
780
|
private fun layoutPagerIfRequested() {
|
|
731
781
|
val recycler = pager.getChildAt(0) as? RecyclerView ?: return
|
|
732
|
-
|
|
733
|
-
|
|
782
|
+
val controlledSettlement = nativeTabBarView.usesControlledTextProgress() || nativeTabBarView.usesSettledToolbarOwner()
|
|
783
|
+
if (controlledSettlement && !isLaidOut && isAttachedToWindow && isShown &&
|
|
784
|
+
width > 0 && height > 0 && pager.width > 0 && pager.height > 0 &&
|
|
785
|
+
pager.scrollState == ViewPager2.SCROLL_STATE_IDLE && !pager.isFakeDragging &&
|
|
786
|
+
pager.currentItem in 0 until adapter.itemCount && !isPagerRecyclerLayoutSuppressed() &&
|
|
787
|
+
!recycler.isLayoutSuppressed && !recycler.isComputingLayout) {
|
|
788
|
+
// A retained Fabric host can reattach with bounds but no completed layout.
|
|
789
|
+
updateHeaderLayout()
|
|
790
|
+
}
|
|
791
|
+
if (controlledSettlement && pager.isLayoutRequested && isAttachedToWindow && isLaidOut &&
|
|
792
|
+
width > 0 && height > 0 && pager.width > 0 && pager.height > 0 &&
|
|
793
|
+
pager.scrollState == ViewPager2.SCROLL_STATE_IDLE && !pager.isFakeDragging &&
|
|
794
|
+
pager.currentItem in 0 until adapter.itemCount && !isPagerRecyclerLayoutSuppressed() &&
|
|
795
|
+
!recycler.isLayoutSuppressed && !recycler.isComputingLayout) {
|
|
796
|
+
// RN can stop the parent request after the recycler has already laid out.
|
|
797
|
+
pager.measure(
|
|
798
|
+
MeasureSpec.makeMeasureSpec(pager.width, MeasureSpec.EXACTLY),
|
|
799
|
+
MeasureSpec.makeMeasureSpec(pager.height, MeasureSpec.EXACTLY),
|
|
800
|
+
)
|
|
801
|
+
pager.layout(pager.left, pager.top, pager.right, pager.bottom)
|
|
802
|
+
}
|
|
803
|
+
if (shouldDrainCollapsiblePagerLayout(
|
|
734
804
|
recycler.isLayoutRequested,
|
|
735
805
|
recycler.isLayoutSuppressed,
|
|
736
806
|
recycler.isComputingLayout,
|
|
737
807
|
recycler.width,
|
|
738
808
|
recycler.height,
|
|
739
809
|
adapter.itemCount,
|
|
810
|
+
)) {
|
|
811
|
+
// OneKey patch: a non-animated page command queues RecyclerView layout, but RN
|
|
812
|
+
// can stop that request after navigation. Drain it before showing the page.
|
|
813
|
+
recycler.measure(
|
|
814
|
+
MeasureSpec.makeMeasureSpec(recycler.width, MeasureSpec.EXACTLY),
|
|
815
|
+
MeasureSpec.makeMeasureSpec(recycler.height, MeasureSpec.EXACTLY),
|
|
740
816
|
)
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
recycler.measure(
|
|
745
|
-
MeasureSpec.makeMeasureSpec(recycler.width, MeasureSpec.EXACTLY),
|
|
746
|
-
MeasureSpec.makeMeasureSpec(recycler.height, MeasureSpec.EXACTLY),
|
|
747
|
-
)
|
|
748
|
-
recycler.layout(recycler.left, recycler.top, recycler.right, recycler.bottom)
|
|
817
|
+
recycler.layout(recycler.left, recycler.top, recycler.right, recycler.bottom)
|
|
818
|
+
}
|
|
819
|
+
if (controlledSettlement) settleNativeTabProgressIfReady()
|
|
749
820
|
}
|
|
750
821
|
|
|
751
822
|
private fun updateHeaderLayout() {
|
|
@@ -843,6 +914,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
843
914
|
postForCurrentAttachment {
|
|
844
915
|
prepareAdjacentPages()
|
|
845
916
|
attachPrimaryScrollObserver()
|
|
917
|
+
settleNativeTabProgressIfReady()
|
|
846
918
|
}
|
|
847
919
|
}
|
|
848
920
|
|
|
@@ -2451,6 +2523,9 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
2451
2523
|
override fun onAttachedToWindow() {
|
|
2452
2524
|
super.onAttachedToWindow()
|
|
2453
2525
|
attachmentGeneration += 1
|
|
2526
|
+
toolbarSettledStamp = null
|
|
2527
|
+
toolbarSettlePostedGeneration = null
|
|
2528
|
+
postForCurrentAttachment { settleNativeTabProgressIfReady() }
|
|
2454
2529
|
restoredRecyclerKeys.clear()
|
|
2455
2530
|
restoredScrollerKeys.clear()
|
|
2456
2531
|
viewTreeObserver.addOnPreDrawListener(pageContentLayoutListener)
|
|
@@ -2468,6 +2543,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
2468
2543
|
}
|
|
2469
2544
|
|
|
2470
2545
|
override fun onDetachedFromWindow() {
|
|
2546
|
+
suspendNativeToolbar()
|
|
2471
2547
|
cancelHeaderSettledCheck()
|
|
2472
2548
|
headerCommandOwner = null
|
|
2473
2549
|
publishHeaderSettledState(false)
|