@onekeyfe/react-native-pager-view 6.7.0-alpha.436 → 6.7.0-alpha.449

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.
Files changed (25) hide show
  1. package/README.md +16 -0
  2. package/android/build.gradle +1 -0
  3. package/android/src/androidTest/java/com/reactnativepagerview/CollapsiblePagerTabReservationTest.kt +135 -0
  4. package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +88 -12
  5. package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerNativeHeaders.kt +442 -15
  6. package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +11 -1
  7. package/android/src/main/java/com/reactnativepagerview/event/NativeHeaderPressEvent.kt +8 -0
  8. package/docs/SPEC.md +298 -3
  9. package/ios/RNCCollapsiblePagerViewComponentView.mm +834 -20
  10. package/ios/tests/RNCCollapsiblePagerFirstFrameTests.mm +61 -0
  11. package/ios/tests/RNCCollapsiblePagerHitTestTests.mm +22 -0
  12. package/lib/module/CollapsiblePagerView.js +37 -5
  13. package/lib/module/CollapsiblePagerView.web.js +519 -6
  14. package/lib/module/CollapsiblePagerViewNativeComponent.ts +6 -0
  15. package/lib/module/NativeScrollerNativeComponent.ts +0 -1
  16. package/lib/typescript/src/CollapsiblePagerView.d.ts +31 -2
  17. package/lib/typescript/src/CollapsiblePagerView.web.d.ts +44 -1
  18. package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +11 -0
  19. package/lib/typescript/src/NativeScroller.d.ts +2 -2
  20. package/package.json +3 -2
  21. package/src/CollapsiblePagerView.tsx +68 -5
  22. package/src/CollapsiblePagerView.web.tsx +464 -5
  23. package/src/CollapsiblePagerViewNativeComponent.ts +6 -0
  24. package/src/NativeScroller.tsx +2 -3
  25. 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.
@@ -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()) {
@@ -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
- if (
733
- !shouldDrainCollapsiblePagerLayout(
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
- ) return
742
- // OneKey patch: a non-animated page command queues RecyclerView layout, but RN
743
- // can stop that request after navigation. Drain it before showing the page.
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)