react-native-screens 4.7.0-beta.0 → 4.7.0-beta.2

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.
@@ -95,6 +95,14 @@ def safeAppExtGet(prop, fallback) {
95
95
  appProject?.ext?.has(prop) ? appProject.ext.get(prop) : fallback
96
96
  }
97
97
 
98
+ def reactNativeRootDir = resolveReactNativeDirectory()
99
+
100
+ def reactProperties = new Properties()
101
+ file("$reactNativeRootDir/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }
102
+
103
+ def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME")
104
+ def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger()
105
+
98
106
  def IS_NEW_ARCHITECTURE_ENABLED = isNewArchitectureEnabled()
99
107
 
100
108
  android {
@@ -166,6 +174,7 @@ android {
166
174
  sourceSets.main {
167
175
  ext.androidResDir = "src/main/res"
168
176
  java {
177
+ // Architecture specific
169
178
  if (IS_NEW_ARCHITECTURE_ENABLED) {
170
179
  srcDirs += [
171
180
  "src/fabric/java",
@@ -175,6 +184,15 @@ android {
175
184
  "src/paper/java",
176
185
  ]
177
186
  }
187
+
188
+ // Background color resolving
189
+ if (REACT_NATIVE_MINOR_VERSION <= 74) {
190
+ srcDirs += "src/versioned/backgroundcolor/74"
191
+ } else if (REACT_NATIVE_MINOR_VERSION <= 76) {
192
+ srcDirs += "src/versioned/backgroundcolor/76"
193
+ } else {
194
+ srcDirs += "src/versioned/backgroundcolor/latest"
195
+ }
178
196
  }
179
197
  res {
180
198
  if (safeExtGet(['compileSdkVersion', 'compileSdk'], rnsDefaultCompileSdkVersion) >= 33) {
@@ -188,7 +206,7 @@ android {
188
206
 
189
207
  repositories {
190
208
  maven {
191
- url "${resolveReactNativeDirectory()}/android"
209
+ url "${reactNativeRootDir}/android"
192
210
  }
193
211
 
194
212
  mavenCentral()
@@ -5,6 +5,7 @@ import android.content.pm.ActivityInfo
5
5
  import android.graphics.Paint
6
6
  import android.os.Parcelable
7
7
  import android.util.SparseArray
8
+ import android.view.MotionEvent
8
9
  import android.view.View
9
10
  import android.view.ViewGroup
10
11
  import android.view.WindowManager
@@ -17,6 +18,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
17
18
  import com.facebook.react.bridge.GuardedRunnable
18
19
  import com.facebook.react.bridge.ReactContext
19
20
  import com.facebook.react.uimanager.PixelUtil
21
+ import com.facebook.react.uimanager.ThemedReactContext
20
22
  import com.facebook.react.uimanager.UIManagerHelper
21
23
  import com.facebook.react.uimanager.UIManagerModule
22
24
  import com.facebook.react.uimanager.events.EventDispatcher
@@ -24,13 +26,16 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
24
26
  import com.google.android.material.shape.CornerFamily
25
27
  import com.google.android.material.shape.MaterialShapeDrawable
26
28
  import com.google.android.material.shape.ShapeAppearanceModel
29
+ import com.swmansion.rnscreens.bottomsheet.isSheetFitToContents
30
+ import com.swmansion.rnscreens.bottomsheet.usesFormSheetPresentation
27
31
  import com.swmansion.rnscreens.events.HeaderHeightChangeEvent
28
32
  import com.swmansion.rnscreens.events.SheetDetentChangedEvent
33
+ import com.swmansion.rnscreens.ext.parentAsViewGroup
29
34
  import java.lang.ref.WeakReference
30
35
 
31
36
  @SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
32
37
  class Screen(
33
- val reactContext: ReactContext,
38
+ val reactContext: ThemedReactContext,
34
39
  ) : FabricEnabledViewGroup(reactContext),
35
40
  ScreenContentWrapper.OnLayoutCallback {
36
41
  val fragment: Fragment?
@@ -81,6 +86,13 @@ class Screen(
81
86
  var sheetClosesOnTouchOutside = true
82
87
  var sheetElevation: Float = 24F
83
88
 
89
+ /**
90
+ * When using form sheet presentation we want to delay enter transition **on Paper** in order
91
+ * to wait for initial layout from React, otherwise the animator-based animation will look
92
+ * glitchy. *This is not needed on Fabric*.
93
+ */
94
+ var shouldTriggerPostponedTransitionAfterLayout = false
95
+
84
96
  var footer: ScreenFooter? = null
85
97
  set(value) {
86
98
  if (value == null && field != null) {
@@ -110,7 +122,7 @@ class Screen(
110
122
  * `fitToContents` for formSheets, as this is first entry point where we can acquire
111
123
  * height of our content.
112
124
  */
113
- override fun onLayoutCallback(
125
+ override fun onContentWrapperLayout(
114
126
  changed: Boolean,
115
127
  left: Int,
116
128
  top: Int,
@@ -119,12 +131,23 @@ class Screen(
119
131
  ) {
120
132
  val height = bottom - top
121
133
 
122
- if (sheetDetents.count() == 1 && sheetDetents.first() == SHEET_FIT_TO_CONTENTS) {
134
+ if (isSheetFitToContents()) {
123
135
  sheetBehavior?.let {
124
136
  if (it.maxHeight != height) {
125
137
  it.maxHeight = height
126
138
  }
127
139
  }
140
+
141
+ if (!BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
142
+ // On old architecture we delay enter transition in order to wait for initial frame.
143
+ shouldTriggerPostponedTransitionAfterLayout = true
144
+ val parent = parentAsViewGroup()
145
+ if (parent != null && !parent.isInLayout) {
146
+ // There are reported cases (irreproducible) when Screen is not laid out after
147
+ // maxHeight is set on behaviour.
148
+ parent.requestLayout()
149
+ }
150
+ }
128
151
  }
129
152
  }
130
153
 
@@ -162,6 +185,17 @@ class Screen(
162
185
 
163
186
  footer?.onParentLayout(changed, l, t, r, b, container!!.height)
164
187
  notifyHeaderHeightChange(t)
188
+
189
+ if (!BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
190
+ maybeTriggerPostponedTransition()
191
+ }
192
+ }
193
+ }
194
+
195
+ private fun maybeTriggerPostponedTransition() {
196
+ if (shouldTriggerPostponedTransitionAfterLayout) {
197
+ shouldTriggerPostponedTransitionAfterLayout = false
198
+ fragment?.startPostponedEnterTransition()
165
199
  }
166
200
  }
167
201
 
@@ -377,6 +411,28 @@ class Screen(
377
411
  }
378
412
  }
379
413
 
414
+ fun endRemovalTransition() {
415
+ if (!isBeingRemoved) {
416
+ return
417
+ }
418
+ isBeingRemoved = false
419
+ endTransitionRecursive(this)
420
+ }
421
+
422
+ private fun endTransitionRecursive(parent: ViewGroup) {
423
+ parent.children.forEach { childView ->
424
+ parent.endViewTransition(childView)
425
+
426
+ if (childView is ScreenStackHeaderConfig) {
427
+ endTransitionRecursive(childView.toolbar)
428
+ }
429
+
430
+ if (childView is ViewGroup) {
431
+ endTransitionRecursive(childView)
432
+ }
433
+ }
434
+ }
435
+
380
436
  private fun startTransitionRecursive(parent: ViewGroup?) {
381
437
  parent?.let {
382
438
  for (i in 0 until it.childCount) {
@@ -407,6 +463,17 @@ class Screen(
407
463
  }
408
464
  }
409
465
 
466
+ // We do not want to perform any action, therefore do not need to override the associated method.
467
+ @SuppressLint("ClickableViewAccessibility")
468
+ override fun onTouchEvent(event: MotionEvent?): Boolean =
469
+ if (usesFormSheetPresentation()) {
470
+ // If we're a form sheet we want to consume the gestures to prevent
471
+ // DimmingView's callback from triggering when clicking on the sheet itself.
472
+ true
473
+ } else {
474
+ super.onTouchEvent(event)
475
+ }
476
+
410
477
  private fun notifyHeaderHeightChange(headerHeight: Int) {
411
478
  val screenContext = context as ReactContext
412
479
  val surfaceId = UIManagerHelper.getSurfaceId(screenContext)
@@ -17,7 +17,7 @@ class ScreenContentWrapper(
17
17
  internal var delegate: OnLayoutCallback? = null
18
18
 
19
19
  interface OnLayoutCallback {
20
- fun onLayoutCallback(
20
+ fun onContentWrapperLayout(
21
21
  changed: Boolean,
22
22
  left: Int,
23
23
  top: Int,
@@ -33,6 +33,6 @@ class ScreenContentWrapper(
33
33
  right: Int,
34
34
  bottom: Int,
35
35
  ) {
36
- delegate?.onLayoutCallback(changed, left, top, right, bottom)
36
+ delegate?.onContentWrapperLayout(changed, left, top, right, bottom)
37
37
  }
38
38
  }
@@ -15,7 +15,6 @@ import com.facebook.react.bridge.UiThreadUtil
15
15
  import com.facebook.react.uimanager.UIManagerHelper
16
16
  import com.facebook.react.uimanager.events.Event
17
17
  import com.facebook.react.uimanager.events.EventDispatcher
18
- import com.swmansion.rnscreens.bottomsheet.DimmingFragment
19
18
  import com.swmansion.rnscreens.events.HeaderBackButtonClickedEvent
20
19
  import com.swmansion.rnscreens.events.ScreenAppearEvent
21
20
  import com.swmansion.rnscreens.events.ScreenDisappearEvent
@@ -290,12 +289,7 @@ open class ScreenFragment :
290
289
  // since we subscribe to parent's animation start/end and dispatch events in child from there
291
290
  // check for `isTransitioning` should be enough since the child's animation should take only
292
291
  // 20ms due to always being `StackAnimation.NONE` when nested stack being pushed
293
- val parent =
294
- if (parentFragment is DimmingFragment) {
295
- parentFragment?.parentFragment
296
- } else {
297
- parentFragment
298
- }
292
+ val parent = parentFragment
299
293
  if (parent == null || (parent is ScreenFragment && !parent.isTransitioning)) {
300
294
  // onViewAnimationStart/End is triggered from View#onAnimationStart/End method of the fragment's root
301
295
  // view. We override an appropriate method of the StackFragment's
@@ -7,11 +7,10 @@ import android.view.View
7
7
  import com.facebook.react.bridge.ReactContext
8
8
  import com.facebook.react.uimanager.UIManagerHelper
9
9
  import com.swmansion.rnscreens.Screen.StackAnimation
10
- import com.swmansion.rnscreens.bottomsheet.DimmingFragment
10
+ import com.swmansion.rnscreens.bottomsheet.isSheetFitToContents
11
11
  import com.swmansion.rnscreens.events.StackFinishTransitioningEvent
12
12
  import java.util.Collections
13
13
  import kotlin.collections.ArrayList
14
- import kotlin.collections.HashSet
15
14
 
16
15
  class ScreenStack(
17
16
  context: Context?,
@@ -50,7 +49,7 @@ class ScreenStack(
50
49
 
51
50
  override fun adapt(screen: Screen): ScreenStackFragmentWrapper =
52
51
  when (screen.stackPresentation) {
53
- Screen.StackPresentation.FORM_SHEET -> DimmingFragment(ScreenStackFragment(screen))
52
+ Screen.StackPresentation.FORM_SHEET -> ScreenStackFragment(screen)
54
53
  else -> ScreenStackFragment(screen)
55
54
  }
56
55
 
@@ -242,7 +241,6 @@ class ScreenStack(
242
241
  }
243
242
  }
244
243
  }
245
-
246
244
  // animation logic end
247
245
  goingForward = shouldUseOpenAnimation
248
246
 
@@ -302,6 +300,12 @@ class ScreenStack(
302
300
  }
303
301
  }
304
302
  } else if (newTop != null && !newTop.fragment.isAdded) {
303
+ if (!BuildConfig.IS_NEW_ARCHITECTURE_ENABLED && newTop.screen.isSheetFitToContents()) {
304
+ // On old architecture the content wrapper might not have received its frame yet,
305
+ // which is required to determine height of the sheet after animation. Therefore
306
+ // we delay the transition and trigger it after views receive the layout.
307
+ newTop.fragment.postponeEnterTransition()
308
+ }
305
309
  it.add(id, newTop.fragment)
306
310
  }
307
311
  topScreenWrapper = newTop as? ScreenStackFragmentWrapper
@@ -1,5 +1,8 @@
1
1
  package com.swmansion.rnscreens
2
2
 
3
+ import android.animation.Animator
4
+ import android.animation.AnimatorSet
5
+ import android.animation.ValueAnimator
3
6
  import android.annotation.SuppressLint
4
7
  import android.content.Context
5
8
  import android.graphics.Color
@@ -16,7 +19,6 @@ import android.view.WindowInsets
16
19
  import android.view.WindowManager
17
20
  import android.view.animation.Animation
18
21
  import android.view.animation.AnimationSet
19
- import android.view.animation.AnimationUtils
20
22
  import android.view.animation.Transformation
21
23
  import android.view.inputmethod.InputMethodManager
22
24
  import android.widget.LinearLayout
@@ -27,6 +29,7 @@ import androidx.core.view.WindowInsetsCompat
27
29
  import com.facebook.react.uimanager.PixelUtil
28
30
  import com.facebook.react.uimanager.PointerEvents
29
31
  import com.facebook.react.uimanager.ReactPointerEventsView
32
+ import com.facebook.react.uimanager.UIManagerHelper
30
33
  import com.google.android.material.appbar.AppBarLayout
31
34
  import com.google.android.material.appbar.AppBarLayout.ScrollingViewBehavior
32
35
  import com.google.android.material.bottomsheet.BottomSheetBehavior
@@ -34,14 +37,20 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCa
34
37
  import com.google.android.material.shape.CornerFamily
35
38
  import com.google.android.material.shape.MaterialShapeDrawable
36
39
  import com.google.android.material.shape.ShapeAppearanceModel
40
+ import com.swmansion.rnscreens.bottomsheet.DimmingViewManager
41
+ import com.swmansion.rnscreens.bottomsheet.SheetDelegate
37
42
  import com.swmansion.rnscreens.bottomsheet.SheetUtils
38
43
  import com.swmansion.rnscreens.bottomsheet.isSheetFitToContents
39
44
  import com.swmansion.rnscreens.bottomsheet.useSingleDetent
40
45
  import com.swmansion.rnscreens.bottomsheet.useThreeDetents
41
46
  import com.swmansion.rnscreens.bottomsheet.useTwoDetents
42
47
  import com.swmansion.rnscreens.bottomsheet.usesFormSheetPresentation
48
+ import com.swmansion.rnscreens.events.ScreenDismissedEvent
49
+ import com.swmansion.rnscreens.events.ScreenEventDelegate
43
50
  import com.swmansion.rnscreens.ext.recycle
51
+ import com.swmansion.rnscreens.transition.ExternalBoundaryValuesEvaluator
44
52
  import com.swmansion.rnscreens.utils.DeviceUtils
53
+ import com.swmansion.rnscreens.utils.resolveBackgroundColor
45
54
 
46
55
  sealed class KeyboardState
47
56
 
@@ -76,6 +85,13 @@ class ScreenStackFragment :
76
85
  return container
77
86
  }
78
87
 
88
+ private val dimmingDelegate =
89
+ lazy(LazyThreadSafetyMode.NONE) {
90
+ DimmingViewManager(screen.reactContext, screen)
91
+ }
92
+
93
+ private var sheetDelegate: SheetDelegate? = null
94
+
79
95
  @SuppressLint("ValidFragment")
80
96
  constructor(screenView: Screen) : super(screenView)
81
97
 
@@ -131,7 +147,12 @@ class ScreenStackFragment :
131
147
 
132
148
  override fun onViewAnimationEnd() {
133
149
  super.onViewAnimationEnd()
150
+
151
+ // Rely on guards inside the callee to detect whether this was indeed appear transition.
134
152
  notifyViewAppearTransitionEnd()
153
+
154
+ // Rely on guards inside the callee to detect whether this was indeed removal transition.
155
+ screen.endRemovalTransition()
135
156
  }
136
157
 
137
158
  private fun notifyViewAppearTransitionEnd() {
@@ -176,7 +197,7 @@ class ScreenStackFragment :
176
197
  }
177
198
 
178
199
  if (newState == BottomSheetBehavior.STATE_HIDDEN) {
179
- nativeDismissalObserver?.onNativeDismiss(this@ScreenStackFragment)
200
+ dismissSelf()
180
201
  }
181
202
  }
182
203
 
@@ -186,18 +207,17 @@ class ScreenStackFragment :
186
207
  ) = Unit
187
208
  }
188
209
 
189
- override fun onCreateAnimation(
190
- transit: Int,
191
- enter: Boolean,
192
- nextAnim: Int,
193
- ): Animation? {
194
- if (screen.stackPresentation != Screen.StackPresentation.FORM_SHEET) {
195
- return null
196
- }
197
- return if (enter) {
198
- AnimationUtils.loadAnimation(context, R.anim.rns_slide_in_from_bottom)
199
- } else {
200
- AnimationUtils.loadAnimation(context, R.anim.rns_slide_out_to_bottom)
210
+ /**
211
+ * Currently this method dispatches event to JS where state is recomputed and fragment
212
+ * gets removed in the result of incoming state update.
213
+ */
214
+ internal fun dismissSelf() {
215
+ if (!this.isRemoving || !this.isDetached) {
216
+ val reactContext = screen.reactContext
217
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
218
+ UIManagerHelper
219
+ .getEventDispatcherForReactTag(reactContext, screen.id)
220
+ ?.dispatchEvent(ScreenDismissedEvent(surfaceId, screen.id))
201
221
  }
202
222
  }
203
223
 
@@ -205,6 +225,10 @@ class ScreenStackFragment :
205
225
  screen.onSheetCornerRadiusChange()
206
226
  }
207
227
 
228
+ override fun onCreate(savedInstanceState: Bundle?) {
229
+ super.onCreate(savedInstanceState)
230
+ }
231
+
208
232
  override fun onCreateView(
209
233
  inflater: LayoutInflater,
210
234
  container: ViewGroup?,
@@ -262,6 +286,90 @@ class ScreenStackFragment :
262
286
  return coordinatorLayout
263
287
  }
264
288
 
289
+ override fun onViewCreated(
290
+ view: View,
291
+ savedInstanceState: Bundle?,
292
+ ) {
293
+ super.onViewCreated(view, savedInstanceState)
294
+
295
+ if (!screen.usesFormSheetPresentation()) {
296
+ return
297
+ }
298
+
299
+ sheetDelegate = SheetDelegate(screen)
300
+
301
+ assert(view == coordinatorLayout)
302
+ dimmingDelegate.value.onViewHierarchyCreated(screen, coordinatorLayout)
303
+ dimmingDelegate.value.onBehaviourAttached(screen, screen.sheetBehavior!!)
304
+
305
+ val container = screen.container!!
306
+ coordinatorLayout.measure(
307
+ View.MeasureSpec.makeMeasureSpec(container.width, View.MeasureSpec.EXACTLY),
308
+ View.MeasureSpec.makeMeasureSpec(container.height, View.MeasureSpec.EXACTLY),
309
+ )
310
+ coordinatorLayout.layout(0, 0, container.width, container.height)
311
+ }
312
+
313
+ override fun onCreateAnimation(
314
+ transit: Int,
315
+ enter: Boolean,
316
+ nextAnim: Int,
317
+ ): Animation? {
318
+ // Ensure onCreateAnimator is called
319
+ return null
320
+ }
321
+
322
+ override fun onCreateAnimator(
323
+ transit: Int,
324
+ enter: Boolean,
325
+ nextAnim: Int,
326
+ ): Animator? {
327
+ if (!screen.usesFormSheetPresentation()) {
328
+ // Use animation defined while defining transaction in screen stack
329
+ return null
330
+ }
331
+
332
+ val animatorSet = AnimatorSet()
333
+
334
+ if (enter) {
335
+ val alphaAnimator =
336
+ ValueAnimator.ofFloat(0f, dimmingDelegate.value.maxAlpha).apply {
337
+ addUpdateListener { anim ->
338
+ val animatedValue = anim.animatedValue as? Float
339
+ animatedValue?.let { dimmingDelegate.value.dimmingView.alpha = it }
340
+ }
341
+ }
342
+ val startValueCallback = { initialStartValue: Number? -> screen.height.toFloat() }
343
+ val evaluator = ExternalBoundaryValuesEvaluator(startValueCallback, { 0f })
344
+ val slideAnimator =
345
+ ValueAnimator.ofObject(evaluator, screen.height.toFloat(), 0f).apply {
346
+ addUpdateListener { anim ->
347
+ val animatedValue = anim.animatedValue as? Float
348
+ animatedValue?.let { screen.translationY = it }
349
+ }
350
+ }
351
+ animatorSet.play(alphaAnimator).with(slideAnimator)
352
+ } else {
353
+ val alphaAnimator =
354
+ ValueAnimator.ofFloat(dimmingDelegate.value.dimmingView.alpha, 0f).apply {
355
+ addUpdateListener { anim ->
356
+ val animatedValue = anim.animatedValue as? Float
357
+ animatedValue?.let { dimmingDelegate.value.dimmingView.alpha = it }
358
+ }
359
+ }
360
+ val slideAnimator =
361
+ ValueAnimator.ofFloat(0f, (coordinatorLayout.bottom - screen.top).toFloat()).apply {
362
+ addUpdateListener { anim ->
363
+ val animatedValue = anim.animatedValue as? Float
364
+ animatedValue?.let { screen.translationY = it }
365
+ }
366
+ }
367
+ animatorSet.play(alphaAnimator).with(slideAnimator)
368
+ }
369
+ animatorSet.addListener(ScreenEventDelegate(this))
370
+ return animatorSet
371
+ }
372
+
265
373
  /**
266
374
  * This method might return slightly different values depending on code path,
267
375
  * but during testing I've found this effect negligible. For practical purposes
@@ -348,7 +456,10 @@ class ScreenStackFragment :
348
456
  behavior.apply {
349
457
  val height =
350
458
  if (screen.isSheetFitToContents()) {
351
- screen.contentWrapper.get()?.height
459
+ screen.contentWrapper
460
+ .get()
461
+ ?.height
462
+ .takeIf { screen.contentWrapper.get()?.isLaidOut == true }
352
463
  } else {
353
464
  (screen.sheetDetents.first() * containerHeight).toInt()
354
465
  }
@@ -456,10 +567,30 @@ class ScreenStackFragment :
456
567
  }
457
568
  }
458
569
 
570
+ private fun createBottomSheetBehaviour(): BottomSheetBehavior<Screen> = BottomSheetBehavior<Screen>()
571
+
459
572
  // In general it would be great to create BottomSheetBehaviour only via this method as it runs some
460
573
  // side effects.
461
- internal fun createAndConfigureBottomSheetBehaviour(): BottomSheetBehavior<Screen> =
462
- configureBottomSheetBehaviour(BottomSheetBehavior<Screen>())
574
+ private fun createAndConfigureBottomSheetBehaviour(): BottomSheetBehavior<Screen> =
575
+ configureBottomSheetBehaviour(createBottomSheetBehaviour())
576
+
577
+ private fun resolveBackgroundColor(screen: Screen): Int? {
578
+ val screenColor =
579
+ (screen.background as? ColorDrawable?)?.color
580
+ ?: (screen.background as? MaterialShapeDrawable?)?.tintList?.defaultColor
581
+
582
+ if (screenColor != null) {
583
+ return screenColor
584
+ }
585
+
586
+ val contentWrapper = screen.contentWrapper.get()
587
+ if (contentWrapper == null) {
588
+ return null
589
+ }
590
+
591
+ val contentWrapperColor = contentWrapper.resolveBackgroundColor()
592
+ return contentWrapperColor
593
+ }
463
594
 
464
595
  private fun attachShapeToScreen(screen: Screen) {
465
596
  val cornerSize = PixelUtil.toPixelFromDIP(screen.sheetCornerRadius)
@@ -471,10 +602,8 @@ class ScreenStackFragment :
471
602
  setTopRightCorner(CornerFamily.ROUNDED, cornerSize)
472
603
  }.build()
473
604
  val shape = MaterialShapeDrawable(shapeAppearanceModel)
474
- val currentColor =
475
- (screen.background as? ColorDrawable?)?.color
476
- ?: (screen.background as? MaterialShapeDrawable?)?.tintList?.defaultColor
477
- shape.setTint(currentColor ?: Color.TRANSPARENT)
605
+ val backgroundColor = resolveBackgroundColor(screen)
606
+ shape.setTint(backgroundColor ?: Color.TRANSPARENT)
478
607
  screen.background = shape
479
608
  }
480
609
 
@@ -12,7 +12,9 @@ internal fun <T : View> BottomSheetBehavior<T>.useSingleDetent(
12
12
  if (forceExpandedState) {
13
13
  this.state = BottomSheetBehavior.STATE_EXPANDED
14
14
  }
15
- height?.let { maxHeight = height }
15
+ height?.let {
16
+ maxHeight = height
17
+ }
16
18
  return this
17
19
  }
18
20
 
@@ -11,7 +11,7 @@ import com.facebook.react.uimanager.ReactPointerEventsView
11
11
  import com.swmansion.rnscreens.ext.equalWithRespectToEps
12
12
 
13
13
  /**
14
- * Serves as dimming view that can be used as background for some view that not fully fills
14
+ * Serves as dimming view that can be used as background for some view that does not fully fill
15
15
  * the viewport.
16
16
  *
17
17
  * This dimming view has one more additional feature: it blocks gestures if its alpha > 0.
@@ -40,6 +40,8 @@ class DimmingView(
40
40
  b: Int,
41
41
  ) = Unit
42
42
 
43
+ // We do not want to have any action defined here. We just want listeners notified that the click happened.
44
+ @SuppressLint("ClickableViewAccessibility")
43
45
  override fun onTouchEvent(event: MotionEvent?): Boolean {
44
46
  if (blockGestures) {
45
47
  callOnClick()