react-native-nitro-modal 0.3.5-rc → 0.3.7-rc
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.
|
@@ -74,6 +74,9 @@ internal class BottomSheetPresenter(
|
|
|
74
74
|
private var lastDetentIndex = -1
|
|
75
75
|
private var reportedRestingTop = Int.MIN_VALUE
|
|
76
76
|
|
|
77
|
+
/** The detent a settle we started is heading for, until it arrives; -1 otherwise. */
|
|
78
|
+
private var settlingTo = -1
|
|
79
|
+
|
|
77
80
|
/** The behavior is dragging the sheet (as opposed to a nested scroll moving it). */
|
|
78
81
|
private var sheetDragging = false
|
|
79
82
|
|
|
@@ -96,6 +99,8 @@ internal class BottomSheetPresenter(
|
|
|
96
99
|
return
|
|
97
100
|
}
|
|
98
101
|
if (newState == BottomSheetBehavior.STATE_DRAGGING) {
|
|
102
|
+
// The user took over; the behavior picks where it settles.
|
|
103
|
+
settlingTo = -1
|
|
99
104
|
sheetDragging = true
|
|
100
105
|
coordinator.notifyNativeGesture(started = true)
|
|
101
106
|
// A refreshing sheet follows the finger from its lowest detent.
|
|
@@ -106,6 +111,7 @@ internal class BottomSheetPresenter(
|
|
|
106
111
|
}
|
|
107
112
|
val position = states().indexOf(newState)
|
|
108
113
|
if (position < 0 || isDismissing) return
|
|
114
|
+
settlingTo = -1
|
|
109
115
|
presented = true
|
|
110
116
|
// Hideable while entering/exiting; at rest, swipe-to-dismiss follows the prop.
|
|
111
117
|
behavior.isHideable = this@BottomSheetPresenter.config.dismissOnSwipe
|
|
@@ -195,11 +201,12 @@ internal class BottomSheetPresenter(
|
|
|
195
201
|
// Settles with the behavior's own animation, from HIDDEN on show or from
|
|
196
202
|
// wherever a reversed exit got to (back to the detent it left).
|
|
197
203
|
val index = if (lastDetentIndex >= 0) lastDetentIndex else config.clampedInitialDetentIndex
|
|
198
|
-
|
|
204
|
+
settleTo(index)
|
|
199
205
|
}
|
|
200
206
|
}
|
|
201
207
|
|
|
202
208
|
override fun animateOut(fromBackGesture: Boolean, onEnd: () -> Unit) {
|
|
209
|
+
settlingTo = -1
|
|
203
210
|
coordinator.cancelPull()
|
|
204
211
|
if (behavior.state == BottomSheetBehavior.STATE_HIDDEN || !coordinator.isLaidOut) {
|
|
205
212
|
onEnd()
|
|
@@ -261,11 +268,16 @@ internal class BottomSheetPresenter(
|
|
|
261
268
|
|
|
262
269
|
override fun snapToDetent(index: Int) {
|
|
263
270
|
if (!presented || isDismissing) return
|
|
264
|
-
|
|
271
|
+
settleTo(index)
|
|
265
272
|
}
|
|
266
273
|
|
|
267
274
|
override fun onTeardown() = coordinator.release()
|
|
268
275
|
|
|
276
|
+
private fun settleTo(index: Int) {
|
|
277
|
+
settlingTo = index
|
|
278
|
+
behavior.state = stateFor(index)
|
|
279
|
+
}
|
|
280
|
+
|
|
269
281
|
private fun applyAppearance() {
|
|
270
282
|
val radius = activity.dpToPx(config.cornerRadius ?: DEFAULT_CORNER_RADIUS_DP)
|
|
271
283
|
if (radius != cornerRadiusPx) {
|
|
@@ -291,6 +303,7 @@ internal class BottomSheetPresenter(
|
|
|
291
303
|
val bottomInset = systemInsets.bottom
|
|
292
304
|
maxContentHeight = (parentHeight - systemInsets.top - bottomInset).coerceAtLeast(1)
|
|
293
305
|
|
|
306
|
+
val previousHeights = sortedDetents.map { it.height }
|
|
294
307
|
val requested = config.detents.ifEmpty { listOf(Detent.FitContent) }
|
|
295
308
|
val detents = requested
|
|
296
309
|
.mapIndexed { index, detent -> RestingHeight(index, contentHeightFor(detent) + bottomInset) }
|
|
@@ -330,6 +343,16 @@ internal class BottomSheetPresenter(
|
|
|
330
343
|
}
|
|
331
344
|
}
|
|
332
345
|
|
|
346
|
+
// A settle heads for where its detent was when it started, and the
|
|
347
|
+
// behavior only moves a sheet at rest when its detents change: content
|
|
348
|
+
// that grows while the sheet slides in would leave it stopped short.
|
|
349
|
+
// Send the settle to where the detent is now.
|
|
350
|
+
if (heights != previousHeights && settlingTo >= 0 && !isDismissing &&
|
|
351
|
+
behavior.state == BottomSheetBehavior.STATE_SETTLING
|
|
352
|
+
) {
|
|
353
|
+
behavior.state = stateFor(settlingTo)
|
|
354
|
+
}
|
|
355
|
+
|
|
333
356
|
val availableHeight =
|
|
334
357
|
if (Detent.FitContent in requested) maxContentHeight else sheetHeight - bottomInset
|
|
335
358
|
val areaHeight = availableHeight -
|
|
@@ -42,6 +42,7 @@ class NitroModalHostView(context: ThemedReactContext) : ViewGroup(context), Reac
|
|
|
42
42
|
|
|
43
43
|
private val measureAndLayout = Runnable {
|
|
44
44
|
layoutPending = false
|
|
45
|
+
forceLayout()
|
|
45
46
|
measure(
|
|
46
47
|
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
|
47
48
|
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY),
|
|
@@ -78,8 +79,15 @@ class NitroModalHostView(context: ThemedReactContext) : ViewGroup(context), Reac
|
|
|
78
79
|
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
|
79
80
|
// Laid out by Fabric. A modal's children live in the modal window; an
|
|
80
81
|
// inline sheet's layout fills this view.
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
layoutChildren(r - l, b - t)
|
|
83
|
+
if (changed) onLayoutChange?.invoke()
|
|
84
|
+
if (forcePendingLayout()) {
|
|
85
|
+
layoutChildren(r - l, b - t)
|
|
86
|
+
if (forcePendingLayout()) scheduleLayout()
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private fun layoutChildren(width: Int, height: Int) {
|
|
83
91
|
for (i in 0 until childCount) {
|
|
84
92
|
val child = getChildAt(i)
|
|
85
93
|
child.measure(
|
|
@@ -88,7 +96,22 @@ class NitroModalHostView(context: ThemedReactContext) : ViewGroup(context), Reac
|
|
|
88
96
|
)
|
|
89
97
|
child.layout(0, 0, width, height)
|
|
90
98
|
}
|
|
91
|
-
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Whether a view in the sheet's layout waits for a layout pass. Marks the
|
|
103
|
+
* views above it so the next pass reaches it. The React content is laid out
|
|
104
|
+
* by Fabric, and gone views take no part in layout.
|
|
105
|
+
*/
|
|
106
|
+
private fun forcePendingLayout(view: ViewGroup = this): Boolean {
|
|
107
|
+
var pending = false
|
|
108
|
+
for (i in 0 until view.childCount) {
|
|
109
|
+
val child = view.getChildAt(i)
|
|
110
|
+
if (child.visibility == GONE || child is ModalContentRoot) continue
|
|
111
|
+
if ((child is ViewGroup && forcePendingLayout(child)) || child.isLayoutRequested) pending = true
|
|
112
|
+
}
|
|
113
|
+
if (pending && view !== this) view.forceLayout()
|
|
114
|
+
return pending
|
|
92
115
|
}
|
|
93
116
|
|
|
94
117
|
override fun onAttachedToWindow() {
|