Skip to content

Commit bd8e57a

Browse files
authored
[Android] Skip the underlay drawable when it can never be visible (#4359)
## Description `createUnderlayDrawable` always allocated a `PaintDrawable` and installed it as the button's underlay, even when it could not possibly render — a fully transparent `underlayColor`, or every opacity (default, active, hover) left at `0`. That is an allocation and an extra drawable in the layer stack per button, for nothing. It now returns `null` in those cases and `underlayDrawable` is left unset. `hoverUnderlayOpacity` and `activeUnderlayOpacity` also needed `withBackgroundUpdate` setters — previously only `defaultUnderlayOpacity` and `underlayColor` triggered a background rebuild, so setting one of the other two after mount could leave the button without an underlay it should now have. ## Test plan - Buttons with a visible underlay (any of the three opacities non-zero) look and animate unchanged on press and hover. - Buttons with `underlayColor="transparent"` or all-zero opacities render with no underlay. - Changing `activeUnderlayOpacity` / `hoverUnderlayOpacity` at runtime rebuilds the background.
1 parent 1506f6a commit bd8e57a

1 file changed

Lines changed: 16 additions & 2 deletions

File tree

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,11 +580,17 @@ class RNGestureHandlerButtonViewManager :
580580
get() = if (field < 0f) defaultScale else field
581581
var hoverUnderlayOpacity: Float = -1f
582582
get() = if (field < 0f) defaultUnderlayOpacity else field
583+
set(value) = withBackgroundUpdate {
584+
field = value
585+
}
583586
var underlayColor: Int? = null
584587
set(color) = withBackgroundUpdate {
585588
field = color
586589
}
587590
var activeUnderlayOpacity: Float = 0f
591+
set(value) = withBackgroundUpdate {
592+
field = value
593+
}
588594
var defaultUnderlayOpacity: Float = 0f
589595
set(value) = withBackgroundUpdate {
590596
field = value
@@ -1055,7 +1061,15 @@ class RNGestureHandlerButtonViewManager :
10551061
}
10561062
}
10571063

1058-
private fun createUnderlayDrawable(): PaintDrawable {
1064+
private fun createUnderlayDrawable(): PaintDrawable? {
1065+
val isColorTransparent = underlayColor?.let { Color.alpha(it) == 0 } == true
1066+
val hasVisibleOpacity = defaultUnderlayOpacity != 0f ||
1067+
activeUnderlayOpacity != 0f ||
1068+
hoverUnderlayOpacity != 0f
1069+
if (isColorTransparent || !hasVisibleOpacity) {
1070+
return null
1071+
}
1072+
10591073
val drawable = PaintDrawable(underlayColor ?: Color.BLACK)
10601074
drawable.alpha = (defaultUnderlayOpacity * 255).toInt()
10611075
return drawable
@@ -1072,7 +1086,7 @@ class RNGestureHandlerButtonViewManager :
10721086
val underlay = createUnderlayDrawable()
10731087
underlayDrawable = underlay
10741088
// Set this view as callback so ObjectAnimator alpha changes trigger redraws.
1075-
underlay.callback = this
1089+
underlay?.callback = this
10761090

10771091
if (useDrawableOnForeground && selectable != null) {
10781092
// Explicit foreground mode — View natively forwards state/hotspot.

0 commit comments

Comments
 (0)