@onekeyfe/react-native-pager-view 6.7.0-alpha.359 → 6.7.0-alpha.363
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 +0 -5
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerHost.kt +21 -76
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerNativeHeaders.kt +7 -72
- package/android/src/main/java/com/reactnativepagerview/CollapsiblePagerViewManager.kt +0 -27
- package/android/src/main/java/com/reactnativepagerview/NativeScrollerView.kt +6 -50
- package/docs/SPEC.md +1 -101
- package/ios/RNCCollapsiblePagerViewComponentView.mm +12 -124
- package/ios/tests/RNCCollapsiblePagerHitTestTests.mm +0 -178
- package/ios/tests/RNCCollapsiblePagerPressCancellationTests.mm +0 -65
- package/lib/module/CollapsiblePagerView.js +4 -20
- package/lib/module/CollapsiblePagerView.web.js +2 -11
- package/lib/module/CollapsiblePagerViewNativeComponent.ts +0 -13
- package/lib/typescript/src/CollapsiblePagerView.d.ts +1 -6
- package/lib/typescript/src/CollapsiblePagerView.web.d.ts +0 -2
- package/lib/typescript/src/CollapsiblePagerViewNativeComponent.d.ts +0 -5
- package/package.json +2 -2
- package/src/CollapsiblePagerView.tsx +4 -68
- package/src/CollapsiblePagerView.web.tsx +2 -19
- package/src/CollapsiblePagerViewNativeComponent.ts +0 -13
- package/android/src/androidTest/AndroidManifest.xml +0 -7
- package/android/src/androidTest/java/com/reactnativepagerview/CollapsiblePagerTabReservationTest.kt +0 -247
package/README.md
CHANGED
|
@@ -66,11 +66,6 @@ replacing its delegate. Android coordinates nested scroll with the active
|
|
|
66
66
|
Web scroll child can opt in by exposing a DOM element with
|
|
67
67
|
`data-collapsible-pager-scroll`. CSS scroll timelines drive header/sticky
|
|
68
68
|
movement, so React is not updated on each vertical scroll frame.
|
|
69
|
-
`pagerRef.current?.scrollHeaderBy(delta)` immediately moves the active page's
|
|
70
|
-
collapsible header by a finite logical distance, clamped to its measured range.
|
|
71
|
-
`scrollHeaderToOffset(offset)` targets an absolute collapse position, so a
|
|
72
|
-
keyboard's own scroll adjustment cannot add a second relative movement.
|
|
73
|
-
It is useful for revealing a focused field above a keyboard.
|
|
74
69
|
|
|
75
70
|
On Web, `WebCollapsiblePagerView` is an explicit root export of the existing Web
|
|
76
71
|
pager. It measures Header and sticky content when their heights are omitted.
|
|
@@ -142,7 +142,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
142
142
|
private var transitionSourceRecyclerAnchor: RecyclerReadingAnchor? = null
|
|
143
143
|
private val commandBodyKeys = HashSet<String>()
|
|
144
144
|
private var explicitTopCommand: Pair<String, PageRestoreRequest>? = null
|
|
145
|
-
private class PagerTopRequest(view: View, val key: String, val pageIndex: Int, val generation: Int, val
|
|
145
|
+
private class PagerTopRequest(view: View, val key: String, val pageIndex: Int, val generation: Int, val target: Int, val token: Int) {
|
|
146
146
|
val view = WeakReference(view)
|
|
147
147
|
}
|
|
148
148
|
private var pagerTopRequest: PagerTopRequest? = null
|
|
@@ -293,23 +293,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
293
293
|
var onNativeSubHeaderPress: ((Int, String) -> Unit)? = null
|
|
294
294
|
|
|
295
295
|
var nativeTabBarHeight = 44.0
|
|
296
|
-
var nativeTabBarVariant = "underline"
|
|
297
|
-
var nativeTabBarTrailingReservedWidth = 0.0
|
|
298
|
-
set(value) {
|
|
299
|
-
field = if (value.isFinite() && value >= 0.0) value else 0.0
|
|
300
|
-
bringNativeHeadersToFront()
|
|
301
|
-
requestLayout()
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
private fun nativeTabReservationPx(width: Int): Int {
|
|
305
|
-
val reserved = nativeTabBarTrailingReservedWidth
|
|
306
|
-
val density = resources.displayMetrics.density
|
|
307
|
-
return if (reserved.isFinite() && reserved > 0.0 && width > 0 && density > 0f) {
|
|
308
|
-
(reserved.coerceAtMost(width / density.toDouble()) * density).roundToInt()
|
|
309
|
-
} else 0
|
|
310
|
-
}
|
|
311
296
|
var nativeTabBarContentPaddingHorizontal = 20.0
|
|
312
|
-
var nativeTabBarContentPaddingVertical = 0.0
|
|
313
297
|
var nativeTabBarItemSpacing = 8.0
|
|
314
298
|
var nativeTabBarFontSize = 16.0
|
|
315
299
|
var nativeTabBarFontFamily: String? = null
|
|
@@ -432,9 +416,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
432
416
|
fun applyNativeHeaderStyle() {
|
|
433
417
|
nativeTabBarView.updateStyle(
|
|
434
418
|
nativeTabBarHeight,
|
|
435
|
-
nativeTabBarVariant,
|
|
436
419
|
nativeTabBarContentPaddingHorizontal,
|
|
437
|
-
nativeTabBarContentPaddingVertical,
|
|
438
420
|
nativeTabBarItemSpacing,
|
|
439
421
|
nativeTabBarFontSize,
|
|
440
422
|
nativeTabBarFontFamily,
|
|
@@ -460,7 +442,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
460
442
|
private fun bringNativeHeadersToFront() {
|
|
461
443
|
nativeTabBarView.bringToFront()
|
|
462
444
|
nativeSubHeaderView.bringToFront()
|
|
463
|
-
if (nativeTabBarTrailingReservedWidth > 0.0) stickyHeaderView?.bringToFront()
|
|
464
445
|
}
|
|
465
446
|
|
|
466
447
|
fun addReactChild(child: View, index: Int) {
|
|
@@ -708,7 +689,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
708
689
|
|
|
709
690
|
private fun layoutPagerIfRequested() {
|
|
710
691
|
val recycler = pager.getChildAt(0) as? RecyclerView ?: return
|
|
711
|
-
if (!recycler.isLayoutRequested || recycler.
|
|
692
|
+
if (!recycler.isLayoutRequested || recycler.isComputingLayout || recycler.width <= 0 || recycler.height <= 0) return
|
|
712
693
|
// OneKey patch: a non-animated page command queues RecyclerView layout, but RN
|
|
713
694
|
// can stop that request after navigation. Drain it before showing the page.
|
|
714
695
|
recycler.measure(
|
|
@@ -731,9 +712,6 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
731
712
|
layout(left, top, right, bottom)
|
|
732
713
|
}
|
|
733
714
|
|
|
734
|
-
private fun isPagerRecyclerLayoutSuppressed(): Boolean =
|
|
735
|
-
(pager.getChildAt(0) as? RecyclerView)?.isLayoutSuppressed == true
|
|
736
|
-
|
|
737
715
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
|
738
716
|
val width = MeasureSpec.getSize(widthMeasureSpec)
|
|
739
717
|
val height = MeasureSpec.getSize(heightMeasureSpec)
|
|
@@ -744,12 +722,10 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
744
722
|
return
|
|
745
723
|
}
|
|
746
724
|
val pagerHeight = height + headerHeightPx
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
)
|
|
752
|
-
}
|
|
725
|
+
pager.measure(
|
|
726
|
+
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
|
727
|
+
MeasureSpec.makeMeasureSpec(pagerHeight, MeasureSpec.EXACTLY),
|
|
728
|
+
)
|
|
753
729
|
headerView?.measure(
|
|
754
730
|
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
|
755
731
|
MeasureSpec.makeMeasureSpec(headerHeightPx, MeasureSpec.EXACTLY),
|
|
@@ -761,9 +737,8 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
761
737
|
val nativeTabHeight = if (nativeTabBarView.visibility == View.VISIBLE) {
|
|
762
738
|
nativeTabBarView.preferredHeightPx()
|
|
763
739
|
} else 0
|
|
764
|
-
val tabReservedWidth = nativeTabReservationPx(width)
|
|
765
740
|
nativeTabBarView.measure(
|
|
766
|
-
MeasureSpec.makeMeasureSpec(width
|
|
741
|
+
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
|
767
742
|
MeasureSpec.makeMeasureSpec(nativeTabHeight, MeasureSpec.EXACTLY),
|
|
768
743
|
)
|
|
769
744
|
val nativeSubHeaderHeight = if (nativeSubHeaderView.visibility == View.VISIBLE) {
|
|
@@ -782,9 +757,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
782
757
|
// RN ancestors allow overflow; keep translated header content inside this viewport.
|
|
783
758
|
clipBounds = Rect(0, 0, width, height)
|
|
784
759
|
if (width <= 0 || height <= 0) return
|
|
785
|
-
|
|
786
|
-
pager.layout(0, 0, width, height + headerHeightPx)
|
|
787
|
-
}
|
|
760
|
+
pager.layout(0, 0, width, height + headerHeightPx)
|
|
788
761
|
headerView?.layout(0, 0, width, headerHeightPx)
|
|
789
762
|
stickyHeaderView?.layout(
|
|
790
763
|
0,
|
|
@@ -793,12 +766,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
793
766
|
headerHeightPx + stickyHeaderHeightPx,
|
|
794
767
|
)
|
|
795
768
|
val nativeTabHeight = nativeTabBarView.measuredHeight
|
|
796
|
-
|
|
797
|
-
val tabLeft = if (nativeTabBarView.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
|
|
798
|
-
tabReservedWidth
|
|
799
|
-
} else 0
|
|
800
|
-
nativeTabBarView.layout(tabLeft, headerHeightPx, tabLeft + width - tabReservedWidth,
|
|
801
|
-
headerHeightPx + nativeTabHeight)
|
|
769
|
+
nativeTabBarView.layout(0, headerHeightPx, width, headerHeightPx + nativeTabHeight)
|
|
802
770
|
nativeSubHeaderView.layout(
|
|
803
771
|
0,
|
|
804
772
|
headerHeightPx + nativeTabHeight,
|
|
@@ -860,7 +828,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
860
828
|
}
|
|
861
829
|
if (!reached()) {
|
|
862
830
|
if (!isAttachedToWindow || !view.isAttachedToWindow || width <= 0 || height <= 0 ||
|
|
863
|
-
view.width <= 0 || view.height <= 0 || isInLayout || view.isInLayout || view.
|
|
831
|
+
view.width <= 0 || view.height <= 0 || isInLayout || view.isInLayout || view.isComputingLayout ||
|
|
864
832
|
pageKey(index) != key || primaryScrollableForPage(index) !== view || !isCurrentPageRestore(key, request)) return false
|
|
865
833
|
val previousSynthetic = syntheticPageRestore
|
|
866
834
|
syntheticPageRestore = true
|
|
@@ -1019,33 +987,13 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
1019
987
|
if (!settled) return
|
|
1020
988
|
pageOffsets[request.key] = 0
|
|
1021
989
|
if (view is RecyclerView) saveRecyclerReadingAnchor(request.key, view)
|
|
1022
|
-
setHeaderOffset(request.
|
|
1023
|
-
offsetDiag("pager-top-complete-
|
|
990
|
+
setHeaderOffset(if (request.target == 1) headerHeightPx else 0)
|
|
991
|
+
offsetDiag("pager-top-complete-target=${request.target}-token=${request.token}", view, request.key)
|
|
1024
992
|
cancelPagerTop()
|
|
1025
993
|
}
|
|
1026
994
|
|
|
1027
995
|
internal fun scrollToTop(target: Int, animated: Boolean) {
|
|
1028
|
-
if (target !in 0..1
|
|
1029
|
-
scrollHeaderToOffset(if (target == 1) headerHeightPx else 0, animated)
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
internal fun scrollHeaderBy(delta: Double) {
|
|
1033
|
-
if (!delta.isFinite()) return
|
|
1034
|
-
val density = resources.displayMetrics.density.toDouble()
|
|
1035
|
-
val maxDip = headerHeightPx / density
|
|
1036
|
-
val deltaPx = (delta.coerceIn(-maxDip, maxDip) * density).roundToInt()
|
|
1037
|
-
scrollHeaderToOffset((headerOffsetPx.toLong() + deltaPx).coerceIn(0, headerHeightPx.toLong()).toInt(), false)
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
internal fun scrollHeaderToOffset(offset: Double) {
|
|
1041
|
-
if (!offset.isFinite()) return
|
|
1042
|
-
val density = resources.displayMetrics.density.toDouble()
|
|
1043
|
-
val targetPx = (offset.coerceIn(0.0, headerHeightPx / density) * density).roundToInt()
|
|
1044
|
-
scrollHeaderToOffset(targetPx, false)
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
private fun scrollHeaderToOffset(logicalOffset: Int, animated: Boolean) {
|
|
1048
|
-
if (pager.scrollState != ViewPager2.SCROLL_STATE_IDLE || transitionHeaderOffsets != null ||
|
|
996
|
+
if (target !in 0..1 || pager.scrollState != ViewPager2.SCROLL_STATE_IDLE || transitionHeaderOffsets != null ||
|
|
1049
997
|
syntheticPageRestore || selectedPage !in 0 until adapter.itemCount || !isAttachedToWindow) return
|
|
1050
998
|
val view = observedRecyclerView ?: observedOwnedScroller ?: observedNativeScroller ?: return
|
|
1051
999
|
val key = currentPageKey()
|
|
@@ -1072,12 +1020,11 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
1072
1020
|
if (view is RecyclerView) deferredRecyclerGeometry.remove(view)
|
|
1073
1021
|
if (view is ScrollView) deferredScrollerGeometry.remove(view)
|
|
1074
1022
|
pageOffsets[key] = 0
|
|
1075
|
-
val
|
|
1076
|
-
val request = PagerTopRequest(view, key, selectedPage, attachmentGeneration, targetOffset, ++pagerTopToken)
|
|
1023
|
+
val request = PagerTopRequest(view, key, selectedPage, attachmentGeneration, target, ++pagerTopToken)
|
|
1077
1024
|
pagerTopRequest = request
|
|
1078
1025
|
commandBodyKeys.add(key)
|
|
1079
|
-
setHeaderOffset(
|
|
1080
|
-
offsetDiag("pager-top-begin-
|
|
1026
|
+
setHeaderOffset(if (target == 1) headerHeightPx else 0)
|
|
1027
|
+
offsetDiag("pager-top-begin-target=$target-animated=$animated-token=${request.token}", view, key)
|
|
1081
1028
|
dispatchingPagerTop = true
|
|
1082
1029
|
try {
|
|
1083
1030
|
when (view) {
|
|
@@ -1086,7 +1033,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
1086
1033
|
if (animated && !recyclerIsAtBodyTop(view)) view.smoothScrollToPosition(0)
|
|
1087
1034
|
else if (manager != null && manager.orientation == RecyclerView.VERTICAL) {
|
|
1088
1035
|
manager.scrollToPositionWithOffset(0, 0)
|
|
1089
|
-
if (view.width > 0 && view.height > 0 && !isInLayout && !view.isInLayout && !view.
|
|
1036
|
+
if (view.width > 0 && view.height > 0 && !isInLayout && !view.isInLayout && !view.isComputingLayout) {
|
|
1090
1037
|
view.measure(MeasureSpec.makeMeasureSpec(view.width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(view.height, MeasureSpec.EXACTLY))
|
|
1091
1038
|
view.layout(view.left, view.top, view.right, view.bottom)
|
|
1092
1039
|
}
|
|
@@ -1691,7 +1638,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
1691
1638
|
if (anchorOffset != null) manager?.scrollToPositionWithOffset(first, anchorOffset)
|
|
1692
1639
|
// React Native can stop this nested requestLayout at its React-owned parent.
|
|
1693
1640
|
// Commit the changed inset before drawing instead of waiting for a data update.
|
|
1694
|
-
if (recycler.width > 0 && recycler.height > 0 && !recycler.
|
|
1641
|
+
if (recycler.width > 0 && recycler.height > 0 && !recycler.isComputingLayout) {
|
|
1695
1642
|
recycler.forceLayout()
|
|
1696
1643
|
recycler.measure(
|
|
1697
1644
|
MeasureSpec.makeMeasureSpec(recycler.width, MeasureSpec.EXACTLY),
|
|
@@ -2065,16 +2012,14 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
2065
2012
|
}
|
|
2066
2013
|
}
|
|
2067
2014
|
|
|
2068
|
-
private fun headerRegionAt(
|
|
2015
|
+
private fun headerRegionAt(y: Float): String? {
|
|
2069
2016
|
val headerBottom = headerHeightPx - headerOffsetPx
|
|
2070
2017
|
val stickyBottom = headerHeightPx + stickyHeaderHeightPx - headerOffsetPx
|
|
2071
2018
|
return when {
|
|
2072
2019
|
y < 0 || y >= stickyBottom -> null
|
|
2073
2020
|
y < headerBottom -> "header"
|
|
2074
2021
|
y < headerBottom + nativeTabBarView.measuredHeight &&
|
|
2075
|
-
nativeTabBarView.visibility == View.VISIBLE ->
|
|
2076
|
-
if (x >= nativeTabBarView.left && x < nativeTabBarView.right) "primary-tab"
|
|
2077
|
-
else "sticky-controls"
|
|
2022
|
+
nativeTabBarView.visibility == View.VISIBLE -> "primary-tab"
|
|
2078
2023
|
y < headerBottom + nativeTabBarView.measuredHeight + nativeSubHeaderView.measuredHeight &&
|
|
2079
2024
|
nativeSubHeaderView.visibility == View.VISIBLE -> "secondary-header"
|
|
2080
2025
|
else -> "sticky-controls"
|
|
@@ -2183,7 +2128,7 @@ class CollapsiblePagerHost(context: Context) : NestedScrollableHost(context), Ne
|
|
|
2183
2128
|
pressCancelled = false
|
|
2184
2129
|
nativeGestureStarted = false
|
|
2185
2130
|
nestedNativeGestureStarted = false
|
|
2186
|
-
headerTouchRegion = headerRegionAt(event.
|
|
2131
|
+
headerTouchRegion = headerRegionAt(event.y) ?: "none"
|
|
2187
2132
|
headerTouchActive = headerTouchRegion != "none"
|
|
2188
2133
|
if (!headerTouchActive) return super.dispatchTouchEvent(event)
|
|
2189
2134
|
headerDownX = event.x
|
|
@@ -65,11 +65,7 @@ private class CollapsiblePagerHorizontalItemsView(
|
|
|
65
65
|
) : HorizontalScrollView(context) {
|
|
66
66
|
private val density = resources.displayMetrics.density
|
|
67
67
|
private val content = FrameLayout(context)
|
|
68
|
-
private val track = View(context)
|
|
69
68
|
private val indicator = View(context)
|
|
70
|
-
private val trackBackground = GradientDrawable().apply {
|
|
71
|
-
shape = GradientDrawable.RECTANGLE
|
|
72
|
-
}
|
|
73
69
|
private val indicatorBackground = GradientDrawable().apply {
|
|
74
70
|
shape = GradientDrawable.RECTANGLE
|
|
75
71
|
}
|
|
@@ -79,8 +75,6 @@ private class CollapsiblePagerHorizontalItemsView(
|
|
|
79
75
|
private var selectedKey = ""
|
|
80
76
|
private var rowHeightPx = dp(if (showsProgressIndicator) 44.0 else 42.0)
|
|
81
77
|
private var contentPaddingPx = dp(20.0)
|
|
82
|
-
private var contentPaddingVerticalPx = 0
|
|
83
|
-
private var segmented = false
|
|
84
78
|
private var itemSpacingPx = dp(8.0)
|
|
85
79
|
private var fontSize = if (showsProgressIndicator) 16.0 else 14.0
|
|
86
80
|
private var fontFamily: String? = null
|
|
@@ -102,9 +96,7 @@ private class CollapsiblePagerHorizontalItemsView(
|
|
|
102
96
|
isFillViewport = true
|
|
103
97
|
overScrollMode = OVER_SCROLL_NEVER
|
|
104
98
|
clipToPadding = false
|
|
105
|
-
track.background = trackBackground
|
|
106
99
|
indicator.background = indicatorBackground
|
|
107
|
-
content.addView(track, FrameLayout.LayoutParams(0, 0))
|
|
108
100
|
content.addView(indicator, FrameLayout.LayoutParams(0, 0))
|
|
109
101
|
addView(
|
|
110
102
|
content,
|
|
@@ -157,24 +149,17 @@ private class CollapsiblePagerHorizontalItemsView(
|
|
|
157
149
|
fontFamily: String?,
|
|
158
150
|
indicatorHeight: Double = 0.0,
|
|
159
151
|
indicatorBottom: Double = 0.0,
|
|
160
|
-
variant: String = "underline",
|
|
161
|
-
contentPaddingVertical: Double = 0.0,
|
|
162
152
|
) {
|
|
163
153
|
rowHeightPx = max(1, dp(rowHeight))
|
|
164
154
|
contentPaddingPx = max(0, dp(contentPadding))
|
|
165
|
-
contentPaddingVerticalPx = max(0, dp(contentPaddingVertical))
|
|
166
|
-
val wasSegmented = segmented
|
|
167
|
-
segmented = showsProgressIndicator && variant == "segmented"
|
|
168
155
|
itemSpacingPx = max(0, dp(itemSpacing))
|
|
169
156
|
this.fontSize = max(1.0, fontSize)
|
|
170
157
|
this.fontFamily = fontFamily
|
|
171
158
|
if (showsProgressIndicator) {
|
|
172
159
|
indicatorHeightPx = max(0, dp(indicatorHeight))
|
|
173
160
|
indicatorBottomPx = max(0, dp(indicatorBottom))
|
|
174
|
-
indicatorBackground.cornerRadius =
|
|
161
|
+
indicatorBackground.cornerRadius = indicatorHeightPx / 2f
|
|
175
162
|
}
|
|
176
|
-
track.visibility = if (segmented) VISIBLE else GONE
|
|
177
|
-
if (segmented && !wasSegmented) scrollTo(0, 0)
|
|
178
163
|
applyTypeface()
|
|
179
164
|
requestLayout()
|
|
180
165
|
}
|
|
@@ -186,9 +171,8 @@ private class CollapsiblePagerHorizontalItemsView(
|
|
|
186
171
|
selectedBackgroundColor: Int,
|
|
187
172
|
indicatorColor: Int,
|
|
188
173
|
) {
|
|
189
|
-
setBackgroundColor(
|
|
190
|
-
content.setBackgroundColor(
|
|
191
|
-
trackBackground.setColor(backgroundColor)
|
|
174
|
+
setBackgroundColor(backgroundColor)
|
|
175
|
+
content.setBackgroundColor(backgroundColor)
|
|
192
176
|
this.activeTextColor = activeTextColor
|
|
193
177
|
this.inactiveTextColor = inactiveTextColor
|
|
194
178
|
this.selectedBackgroundColor = selectedBackgroundColor
|
|
@@ -229,46 +213,6 @@ private class CollapsiblePagerHorizontalItemsView(
|
|
|
229
213
|
}
|
|
230
214
|
applyTypeface()
|
|
231
215
|
itemFrames.clear()
|
|
232
|
-
if (segmented) {
|
|
233
|
-
val actualPaddingHorizontal = min(contentPaddingPx, width / 2)
|
|
234
|
-
val actualPaddingVertical = min(contentPaddingVerticalPx, height / 2)
|
|
235
|
-
val trackLeft = actualPaddingHorizontal
|
|
236
|
-
val trackRight = max(trackLeft, width - contentPaddingPx)
|
|
237
|
-
val trackTop = actualPaddingVertical
|
|
238
|
-
val trackBottom = max(trackTop, height - contentPaddingVerticalPx)
|
|
239
|
-
val trackWidth = trackRight - trackLeft
|
|
240
|
-
val trackHeight = trackBottom - trackTop
|
|
241
|
-
trackBackground.cornerRadius = trackHeight / 2f
|
|
242
|
-
indicatorBackground.cornerRadius = max(0, trackHeight - dp(4.0)) / 2f
|
|
243
|
-
track.layoutParams = FrameLayout.LayoutParams(trackWidth, trackHeight).apply {
|
|
244
|
-
gravity = Gravity.TOP or Gravity.LEFT
|
|
245
|
-
leftMargin = trackLeft
|
|
246
|
-
topMargin = trackTop
|
|
247
|
-
}
|
|
248
|
-
buttons.forEachIndexed { index, button ->
|
|
249
|
-
val count = buttons.size
|
|
250
|
-
val first = trackLeft + trackWidth * index / count
|
|
251
|
-
val last = trackLeft + trackWidth * (index + 1) / count
|
|
252
|
-
val start = if (layoutDirection == View.LAYOUT_DIRECTION_RTL) trackRight - (last - trackLeft) else first
|
|
253
|
-
val end = if (layoutDirection == View.LAYOUT_DIRECTION_RTL) trackRight - (first - trackLeft) else last
|
|
254
|
-
val buttonWidth = max(0, end - start)
|
|
255
|
-
val thumbInset = dp(2.0)
|
|
256
|
-
itemFrames.add(intArrayOf(start, buttonWidth, start + thumbInset, max(0, buttonWidth - 2 * thumbInset)))
|
|
257
|
-
button.layoutParams = FrameLayout.LayoutParams(buttonWidth, trackHeight).apply {
|
|
258
|
-
gravity = Gravity.TOP or Gravity.LEFT
|
|
259
|
-
leftMargin = start
|
|
260
|
-
topMargin = trackTop
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
content.layoutParams = LayoutParams(width, height)
|
|
264
|
-
content.measure(
|
|
265
|
-
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
|
266
|
-
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY),
|
|
267
|
-
)
|
|
268
|
-
setMeasuredDimension(width, height)
|
|
269
|
-
return
|
|
270
|
-
}
|
|
271
|
-
track.layoutParams = FrameLayout.LayoutParams(0, 0)
|
|
272
216
|
var x = contentPaddingPx
|
|
273
217
|
buttons.forEachIndexed { index, button ->
|
|
274
218
|
val textWidth = ceil(button.paint.measureText(button.text.toString()).toDouble()).toInt()
|
|
@@ -316,9 +260,6 @@ private class CollapsiblePagerHorizontalItemsView(
|
|
|
316
260
|
return super.onTouchEvent(event)
|
|
317
261
|
}
|
|
318
262
|
|
|
319
|
-
override fun onInterceptTouchEvent(event: MotionEvent): Boolean =
|
|
320
|
-
if (segmented) false else super.onInterceptTouchEvent(event)
|
|
321
|
-
|
|
322
263
|
private fun updatePresentation() {
|
|
323
264
|
if (buttons.isEmpty() || itemFrames.size != buttons.size) return
|
|
324
265
|
val selectedIndex: Int
|
|
@@ -334,16 +275,14 @@ private class CollapsiblePagerHorizontalItemsView(
|
|
|
334
275
|
val interpolatedIndicatorWidth = from[3] + (to[3] - from[3]) * fraction
|
|
335
276
|
val indicatorX = interpolatedIndicatorX.roundToInt()
|
|
336
277
|
val indicatorWidth = interpolatedIndicatorWidth.roundToInt()
|
|
337
|
-
val
|
|
338
|
-
val indicatorHeight = if (segmented) max(0, measuredHeight - 2 * actualPaddingVertical - dp(4.0)) else indicatorHeightPx
|
|
339
|
-
val indicatorTop = if (segmented) actualPaddingVertical + dp(2.0) else max(0, measuredHeight - indicatorBottomPx - indicatorHeightPx)
|
|
278
|
+
val indicatorTop = max(0, measuredHeight - indicatorBottomPx - indicatorHeightPx)
|
|
340
279
|
indicator.layout(
|
|
341
280
|
indicatorX,
|
|
342
281
|
indicatorTop,
|
|
343
282
|
indicatorX + indicatorWidth,
|
|
344
|
-
indicatorTop +
|
|
283
|
+
indicatorTop + indicatorHeightPx,
|
|
345
284
|
)
|
|
346
|
-
indicator.visibility = if (
|
|
285
|
+
indicator.visibility = if (indicatorHeightPx > 0) VISIBLE else GONE
|
|
347
286
|
scrollTargetCenterX = interpolatedIndicatorX + interpolatedIndicatorWidth / 2f
|
|
348
287
|
selectedIndex = clamped.roundToInt()
|
|
349
288
|
buttons.forEachIndexed { index, button ->
|
|
@@ -365,7 +304,7 @@ private class CollapsiblePagerHorizontalItemsView(
|
|
|
365
304
|
}
|
|
366
305
|
}
|
|
367
306
|
|
|
368
|
-
if (centerSelectionWhenIdle && !
|
|
307
|
+
if (centerSelectionWhenIdle && !isTouchDragging && width > 0 && selectedIndex in itemFrames.indices) {
|
|
369
308
|
val desired = (scrollTargetCenterX - width / 2f).roundToInt()
|
|
370
309
|
.coerceIn(0, max(0, content.measuredWidth - width))
|
|
371
310
|
scrollTo(desired, 0)
|
|
@@ -396,9 +335,7 @@ internal class CollapsiblePagerNativeTabBarView(context: Context) : FrameLayout(
|
|
|
396
335
|
|
|
397
336
|
fun updateStyle(
|
|
398
337
|
height: Double,
|
|
399
|
-
variant: String,
|
|
400
338
|
contentPadding: Double,
|
|
401
|
-
contentPaddingVertical: Double,
|
|
402
339
|
itemSpacing: Double,
|
|
403
340
|
fontSize: Double,
|
|
404
341
|
fontFamily: String?,
|
|
@@ -414,8 +351,6 @@ internal class CollapsiblePagerNativeTabBarView(context: Context) : FrameLayout(
|
|
|
414
351
|
fontFamily,
|
|
415
352
|
indicatorHeight,
|
|
416
353
|
indicatorBottom,
|
|
417
|
-
variant,
|
|
418
|
-
contentPaddingVertical,
|
|
419
354
|
)
|
|
420
355
|
requestLayout()
|
|
421
356
|
}
|
|
@@ -239,18 +239,6 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
|
|
|
239
239
|
view.applyNativeHeaderStyle()
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
@ReactProp(name = "nativeTabBarVariant")
|
|
243
|
-
override fun setNativeTabBarVariant(view: CollapsiblePagerHost?, value: String?) {
|
|
244
|
-
view ?: return
|
|
245
|
-
view.nativeTabBarVariant = if (value == "segmented") "segmented" else "underline"
|
|
246
|
-
view.applyNativeHeaderStyle()
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
@ReactProp(name = "nativeTabBarTrailingReservedWidth", defaultDouble = 0.0)
|
|
250
|
-
override fun setNativeTabBarTrailingReservedWidth(view: CollapsiblePagerHost?, value: Double) {
|
|
251
|
-
view?.nativeTabBarTrailingReservedWidth = value
|
|
252
|
-
}
|
|
253
|
-
|
|
254
242
|
@ReactProp(name = "nativeTabBarContentPaddingHorizontal")
|
|
255
243
|
override fun setNativeTabBarContentPaddingHorizontal(
|
|
256
244
|
view: CollapsiblePagerHost?,
|
|
@@ -261,13 +249,6 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
|
|
|
261
249
|
view.applyNativeHeaderStyle()
|
|
262
250
|
}
|
|
263
251
|
|
|
264
|
-
@ReactProp(name = "nativeTabBarContentPaddingVertical")
|
|
265
|
-
override fun setNativeTabBarContentPaddingVertical(view: CollapsiblePagerHost?, value: Double) {
|
|
266
|
-
view ?: return
|
|
267
|
-
view.nativeTabBarContentPaddingVertical = if (value.isFinite()) value.coerceAtLeast(0.0) else 0.0
|
|
268
|
-
view.applyNativeHeaderStyle()
|
|
269
|
-
}
|
|
270
|
-
|
|
271
252
|
@ReactProp(name = "nativeTabBarItemSpacing")
|
|
272
253
|
override fun setNativeTabBarItemSpacing(view: CollapsiblePagerHost?, value: Double) {
|
|
273
254
|
view ?: return
|
|
@@ -362,14 +343,6 @@ class CollapsiblePagerViewManager : ViewGroupManager<CollapsiblePagerHost>(),
|
|
|
362
343
|
view?.scrollToTop(target, animated)
|
|
363
344
|
}
|
|
364
345
|
|
|
365
|
-
override fun scrollHeaderBy(view: CollapsiblePagerHost?, delta: Double) {
|
|
366
|
-
view?.scrollHeaderBy(delta)
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
override fun scrollHeaderToOffset(view: CollapsiblePagerHost?, offset: Double) {
|
|
370
|
-
view?.scrollHeaderToOffset(offset)
|
|
371
|
-
}
|
|
372
|
-
|
|
373
346
|
override fun setPage(view: CollapsiblePagerHost?, selectedPage: Int) {
|
|
374
347
|
if (view != null && selectedPage in 0 until view.adapter.itemCount) {
|
|
375
348
|
view.beginPageTransition(selectedPage)
|
|
@@ -37,50 +37,26 @@ class NativeScrollerView(context: Context) : FrameLayout(context) {
|
|
|
37
37
|
setMeasuredDimension(MeasureSpec.getSize(widthSpec), MeasureSpec.getSize(heightSpec))
|
|
38
38
|
}
|
|
39
39
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) = Unit
|
|
40
|
-
|
|
41
|
-
override fun startViewTransition(view: View) {
|
|
42
|
-
super.startViewTransition(view)
|
|
43
|
-
if (view === reactChild) transitioningReactChild = view
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
override fun endViewTransition(view: View) {
|
|
47
|
-
super.endViewTransition(view)
|
|
48
|
-
if (transitioningReactChild === view) transitioningReactChild = null
|
|
49
|
-
if (retainedReactChild === view) {
|
|
50
|
-
clearRetainedGeometry()
|
|
51
|
-
if (isAttachedToWindow) scheduleLayout()
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
40
|
}
|
|
55
41
|
private val contentFrame = object : FrameLayout(context) {
|
|
56
42
|
override fun onMeasure(widthSpec: Int, heightSpec: Int) {
|
|
57
43
|
setMeasuredDimension(
|
|
58
|
-
max(MeasureSpec.getSize(widthSpec),
|
|
59
|
-
|
|
44
|
+
max(MeasureSpec.getSize(widthSpec), contentWidthPx + insetLeft + insetRight),
|
|
45
|
+
contentHeightPx + contentTop + insetBottom,
|
|
60
46
|
)
|
|
61
47
|
}
|
|
62
48
|
|
|
63
49
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
64
50
|
// Only the native origin layer moves. Fabric owns its React child's layout/transform.
|
|
65
|
-
val contentWidth = effectiveContentWidthPx
|
|
66
|
-
val contentHeight = effectiveContentHeightPx
|
|
67
51
|
contentOriginFrame.measure(
|
|
68
|
-
MeasureSpec.makeMeasureSpec(
|
|
69
|
-
MeasureSpec.makeMeasureSpec(
|
|
52
|
+
MeasureSpec.makeMeasureSpec(contentWidthPx, MeasureSpec.EXACTLY),
|
|
53
|
+
MeasureSpec.makeMeasureSpec(contentHeightPx, MeasureSpec.EXACTLY),
|
|
70
54
|
)
|
|
71
|
-
contentOriginFrame.layout(insetLeft, contentTop, insetLeft +
|
|
55
|
+
contentOriginFrame.layout(insetLeft, contentTop, insetLeft + contentWidthPx, contentTop + contentHeightPx)
|
|
72
56
|
}
|
|
73
57
|
}
|
|
74
58
|
private val pagerInsets = WeakHashMap<View, Int>()
|
|
75
59
|
private var reactChild: View? = null
|
|
76
|
-
private var transitioningReactChild: View? = null
|
|
77
|
-
private var retainedReactChild: View? = null
|
|
78
|
-
private var retainedContentWidthPx = 0
|
|
79
|
-
private var retainedContentHeightPx = 0
|
|
80
|
-
private val effectiveContentWidthPx: Int
|
|
81
|
-
get() = if (reactChild == null && retainedReactChild != null) retainedContentWidthPx else contentWidthPx
|
|
82
|
-
private val effectiveContentHeightPx: Int
|
|
83
|
-
get() = if (reactChild == null && retainedReactChild != null) retainedContentHeightPx else contentHeightPx
|
|
84
60
|
private var fabricState: StateWrapper? = null
|
|
85
61
|
private var lastOriginX: Int? = null
|
|
86
62
|
private var lastOriginY: Int? = null
|
|
@@ -196,8 +172,6 @@ class NativeScrollerView(context: Context) : FrameLayout(context) {
|
|
|
196
172
|
internal fun addReactChild(child: View, index: Int) {
|
|
197
173
|
require(index == 0 && reactChild == null) { "NativeScroller requires one React content view" }
|
|
198
174
|
viewport.stopMotion()
|
|
199
|
-
clearRetainedGeometry()
|
|
200
|
-
transitioningReactChild = null
|
|
201
175
|
reactChild = child
|
|
202
176
|
contentOriginFrame.addView(child)
|
|
203
177
|
scheduleLayout()
|
|
@@ -206,29 +180,13 @@ class NativeScrollerView(context: Context) : FrameLayout(context) {
|
|
|
206
180
|
internal fun removeReactChild() {
|
|
207
181
|
viewport.stopMotion()
|
|
208
182
|
pendingRestore.cancel()
|
|
209
|
-
reactChild?.let
|
|
210
|
-
clearRetainedGeometry()
|
|
211
|
-
// Fabric removes the child before its disappearing view finishes drawing.
|
|
212
|
-
if (transitioningReactChild === child &&
|
|
213
|
-
contentOriginFrame.width > 0 && contentOriginFrame.height > 0) {
|
|
214
|
-
retainedReactChild = child
|
|
215
|
-
retainedContentWidthPx = contentOriginFrame.width
|
|
216
|
-
retainedContentHeightPx = contentOriginFrame.height
|
|
217
|
-
}
|
|
218
|
-
contentOriginFrame.removeView(child)
|
|
219
|
-
}
|
|
183
|
+
reactChild?.let(contentOriginFrame::removeView)
|
|
220
184
|
reactChild = null
|
|
221
185
|
contentWidthPx = 0
|
|
222
186
|
contentHeightPx = 0
|
|
223
187
|
scheduleLayout()
|
|
224
188
|
}
|
|
225
189
|
|
|
226
|
-
private fun clearRetainedGeometry() {
|
|
227
|
-
retainedReactChild = null
|
|
228
|
-
retainedContentWidthPx = 0
|
|
229
|
-
retainedContentHeightPx = 0
|
|
230
|
-
}
|
|
231
|
-
|
|
232
190
|
internal fun reactChildCount() = if (reactChild == null) 0 else 1
|
|
233
191
|
internal fun reactChildAt(index: Int): View {
|
|
234
192
|
require(index == 0)
|
|
@@ -423,8 +381,6 @@ class NativeScrollerView(context: Context) : FrameLayout(context) {
|
|
|
423
381
|
lastContentViewportHeight = null
|
|
424
382
|
viewport.stopMotion()
|
|
425
383
|
viewport.setTag(R.id.onekey_native_scroll_coordinator_offset_listener, null)
|
|
426
|
-
transitioningReactChild = null
|
|
427
|
-
clearRetainedGeometry()
|
|
428
384
|
super.onDetachedFromWindow()
|
|
429
385
|
}
|
|
430
386
|
|