Skip to content

Commit

Permalink
fix(Android): missing background color for formSheets on RN 0.77+ (#2660
Browse files Browse the repository at this point in the history
)

## Description


* facebook/react-native#45688 introduced
`BackgroundStyleApplicator`
* facebook/react-native#47906 removed our
current accessor
* somewhere along the way the `ColorDrawable` used previously by
`ReactViewGroup` has been exchanged for `CompositeBackgroundDrawable`
added in facebook/react-native#45688

> [!caution]
~This PR breaks compatibility with older versions of react-native. While
this is fine on Fabric, this also breaks things for Paper.~
> ~Possible solution is to detect react native version in gradle and add
versioned sourcesets with implementations for given react native
versions.~
>
> Not up to date. I've added versioned source files to ensure
appropriate backward compatibility down to 0.74.

> [!note]
> We need CI to ensure the projects do build on all versions we support.

## Changes

Migrated to `BackgroundStyleApplicator API` to resolve background color
of `contentWrapper`.

## Test code and steps to reproduce

`TestAndroidTransitions` - the form sheet should no longer be cut.

## Checklist

- [ ] Ensured that CI passes
  • Loading branch information
kkafar authored Jan 31, 2025
1 parent 89f8ad3 commit 32c3a19
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 6 deletions.
20 changes: 19 additions & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ def safeAppExtGet(prop, fallback) {
appProject?.ext?.has(prop) ? appProject.ext.get(prop) : fallback
}

def reactNativeRootDir = resolveReactNativeDirectory()

def reactProperties = new Properties()
file("$reactNativeRootDir/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }

def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME")
def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.startsWith("0.0.0-") ? 1000 : REACT_NATIVE_VERSION.split("\\.")[1].toInteger()

def IS_NEW_ARCHITECTURE_ENABLED = isNewArchitectureEnabled()

android {
Expand Down Expand Up @@ -166,6 +174,7 @@ android {
sourceSets.main {
ext.androidResDir = "src/main/res"
java {
// Architecture specific
if (IS_NEW_ARCHITECTURE_ENABLED) {
srcDirs += [
"src/fabric/java",
Expand All @@ -175,6 +184,15 @@ android {
"src/paper/java",
]
}

// Background color resolving
if (REACT_NATIVE_MINOR_VERSION <= 74) {
srcDirs += "src/versioned/backgroundcolor/74"
} else if (REACT_NATIVE_MINOR_VERSION <= 76) {
srcDirs += "src/versioned/backgroundcolor/76"
} else {
srcDirs += "src/versioned/backgroundcolor/latest"
}
}
res {
if (safeExtGet(['compileSdkVersion', 'compileSdk'], rnsDefaultCompileSdkVersion) >= 33) {
Expand All @@ -188,7 +206,7 @@ android {

repositories {
maven {
url "${resolveReactNativeDirectory()}/android"
url "${reactNativeRootDir}/android"
}

mavenCentral()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import android.widget.LinearLayout
import androidx.annotation.RequiresApi
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.animation.addListener
import androidx.core.view.WindowInsetsCompat
import com.facebook.react.uimanager.PixelUtil
import com.facebook.react.uimanager.PointerEvents
Expand All @@ -51,6 +50,7 @@ import com.swmansion.rnscreens.events.ScreenEventDelegate
import com.swmansion.rnscreens.ext.recycle
import com.swmansion.rnscreens.transition.ExternalBoundaryValuesEvaluator
import com.swmansion.rnscreens.utils.DeviceUtils
import com.swmansion.rnscreens.utils.resolveBackgroundColor

sealed class KeyboardState

Expand Down Expand Up @@ -574,6 +574,24 @@ class ScreenStackFragment :
private fun createAndConfigureBottomSheetBehaviour(): BottomSheetBehavior<Screen> =
configureBottomSheetBehaviour(createBottomSheetBehaviour())

private fun resolveBackgroundColor(screen: Screen): Int? {
val screenColor =
(screen.background as? ColorDrawable?)?.color
?: (screen.background as? MaterialShapeDrawable?)?.tintList?.defaultColor

if (screenColor != null) {
return screenColor
}

val contentWrapper = screen.contentWrapper.get()
if (contentWrapper == null) {
return null
}

val contentWrapperColor = contentWrapper.resolveBackgroundColor()
return contentWrapperColor
}

private fun attachShapeToScreen(screen: Screen) {
val cornerSize = PixelUtil.toPixelFromDIP(screen.sheetCornerRadius)
val shapeAppearanceModel =
Expand All @@ -584,10 +602,8 @@ class ScreenStackFragment :
setTopRightCorner(CornerFamily.ROUNDED, cornerSize)
}.build()
val shape = MaterialShapeDrawable(shapeAppearanceModel)
val currentColor =
(screen.background as? ColorDrawable?)?.color
?: (screen.background as? MaterialShapeDrawable?)?.tintList?.defaultColor
shape.setTint(currentColor ?: Color.TRANSPARENT)
val backgroundColor = resolveBackgroundColor(screen)
shape.setTint(backgroundColor ?: Color.TRANSPARENT)
screen.background = shape
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.swmansion.rnscreens.utils

import com.facebook.react.views.view.ReactViewBackgroundDrawable
import com.facebook.react.views.view.ReactViewGroup

internal fun ReactViewGroup.resolveBackgroundColor(): Int? = (this.background as? ReactViewBackgroundDrawable)?.color
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.swmansion.rnscreens.utils

import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
import com.facebook.react.views.view.ReactViewGroup

@OptIn(UnstableReactNativeAPI::class)
internal fun ReactViewGroup.resolveBackgroundColor(): Int? = (this.background as? CSSBackgroundDrawable)?.color

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.swmansion.rnscreens.utils

import com.facebook.react.common.annotations.UnstableReactNativeAPI
import com.facebook.react.uimanager.BackgroundStyleApplicator
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
import com.facebook.react.views.view.ReactViewGroup

internal fun ReactViewGroup.resolveBackgroundColor(): Int? = BackgroundStyleApplicator.getBackgroundColor(this)

0 comments on commit 32c3a19

Please sign in to comment.