Skip to content

[0.80] Using Android ripple on background (default) does not work #52939

Open

Description

@vanHoi

Description

When using React Native 0.80.x, the Android ripple config does not work any more when not using it on the foreground. Applying a ripple to the background is the default behaviour. When setting the foreground: true, it still works, but that is not the effect we are after.

On React Native 0.79, everything still works like expected.

Steps to reproduce

When using a bare React Native project, just add a really simple Pressable component, for example:

<Pressable android_ripple={{ color: 'blue', foreground: false }} onPress={() => console.log('Pressed!')}>
  <View
    style={{ width: '100%', height: 250 }}
  />
</Pressable>

Then run the app on Android.
Notice that the press event is fired correctly. You do not see any ripple effect.
When setting foreground: true, everything works like expected.

The issue is present on both the old and new architecture.

React Native Version

0.80.2 (it still persists in 0.81.0)

Affected Platforms

Runtime - Android

Output of npx @react-native-community/cli info

System:
  OS: macOS 15.5
  CPU: (12) arm64 Apple M2 Max
  Memory: 61.47 MB / 64.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 22.16.0
    path: ~/.nvm/versions/node/v22.16.0/bin/node
  Yarn:
    version: 1.22.22
    path: ~/.nvm/versions/node/v22.16.0/bin/yarn
  npm:
    version: 10.9.2
    path: ~/.nvm/versions/node/v22.16.0/bin/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.16.2
    path: /Users/ireumkens/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.5
      - iOS 18.5
      - macOS 15.5
      - tvOS 18.5
      - visionOS 2.5
      - watchOS 11.5
  Android SDK:
    API Levels:
      - "27"
      - "29"
      - "32"
      - "34"
      - "35"
    Build Tools:
      - 33.0.1
      - 34.0.0
      - 35.0.0
      - 35.0.0
      - 35.0.0
      - 35.0.1
      - 36.0.0
    System Images:
      - android-27 | ARM 64 v8a
      - android-27 | Intel x86_64 Atom
      - android-34 | Google APIs ARM 64 v8a
      - android-34 | Google Play ARM 64 v8a
      - android-35 | Google Play ARM 64 v8a
      - android-36 | Google Play ARM 64 v8a
    Android NDK: 25.1.8937393
IDEs:
  Android Studio: 2024.3 AI-243.26053.27.2432.13536105
  Xcode:
    version: 16.4/16F6
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.14
    path: /Users/ireumkens/.jenv/shims/javac
  Ruby:
    version: 3.3.0
    path: /Users/ireumkens/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 19.1.1
    wanted: 19.1.1
  react:
    installed: 19.1.0
    wanted: 19.1.0
  react-native:
    installed: 0.80.2
    wanted: 0.80.2
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: false

Stacktrace or Logs

No crash - just unexpected behaviour.

MANDATORY Reproducer

https://github.com/vanHoi/android-ripple-bug

Screenshots and Videos

First I'm tapping the topmost box. Then tapping the bottom box.

ripple.bug.mp4

Activity

  1. react-native-bot commented on Jul 31, 2025

    @react-native-bot
    Collaborator

    Warning

    Could not parse version: We could not find or parse the version number of React Native in your issue report. Please use the template, and report your version including major, minor, and patch numbers - e.g. 0.76.2.

  2. react-native-bot commented on Jul 31, 2025

    @react-native-bot
    Collaborator

    Warning

    Could not parse version: We could not find or parse the version number of React Native in your issue report. Please use the template, and report your version including major, minor, and patch numbers - e.g. 0.76.2.

  3. cortinico commented on Jul 31, 2025

    @cortinico
    Contributor
  4. vanHoi commented on Aug 1, 2025

    @vanHoi
    Author

    Hi @cortinico ,

    Thanks for your quick response. I do think that this is a separate bug however.
    I tried the workaround you mentioned, but it does not fix this issue.

    Also, this issue is introduced with 0.80. In 0.79 it works like it should. Also it is broken on both the old and new architecture.

    I created this snack on Expo 53 (so it should run RN 0.79 with new arch), and there the ripple works like expected. Run the same code on 0.80 and it is broken. Adding the collapsable tag to the parent does not fix it.

    Link: https://snack.expo.dev/@vanhoi/android-ripple?platform=android

  5. cortinico commented on Aug 1, 2025

    @cortinico
    Contributor

    Hi @cortinico ,

    Thanks for your quick response. I do think that this is a separate bug however. I tried the workaround you mentioned, but it does not fix this issue.

    Also, this issue is introduced with 0.80. In 0.79 it works like it should. Also it is broken on both the old and new architecture.

    I created this snack on Expo 53 (so it should run RN 0.79 with new arch), and there the ripple works like expected. Run the same code on 0.80 and it is broken. Adding the collapsable tag to the parent does not fix it.

    Link: snack.expo.dev/@vanhoi/android-ripple?platform=android

    Thanks for the further context.
    We'll need to investigate then which commit of 0.80 introduced this regression

  6. 1 remaining item

  7. Raymond-47 commented on Sep 8, 2025

    @Raymond-47

    I meet the same problem in 0.81, anything new?

  8. Thereallo1026 commented on Sep 22, 2025

    @Thereallo1026

    I'm experiencing this same issue via Expo SDK 54 (which uses RN 0.81.4). In addition to the ripple visibility problem, I've discovered another related issue:

    When android_ripple is present on a Pressable, React context changes don't trigger re-renders on Android. Components won't update their background colors or other theme-dependent styles until navigation occurs.

    Reproduction:

    1. Create a Pressable with android_ripple and dynamic styling from React context (e.g., theme provider)
    2. Change the context values (toggle dark/light theme)
    3. Component styles don't update until you navigate to a different screen
    4. Remove android_ripple > re-renders work instantly

    This suggests the ripple implementation is interfering with React Native's re-render cycle, not just the visual rendering.

    Has anyone else noticed this re-render issue? It seems like whatever broke the ripple visibility also broke React's update detection when ripple is present.

  9. hauck97 commented on Sep 22, 2025

    @hauck97

    The ripple effect is just present with foreground set to true, but child elements are overshadowed by it. Any further here?

  10. ferrannp commented on Sep 28, 2025

    @ferrannp
    Contributor

    Yep, this is broken in 0.81 too (running new arch). foreground: false does nothing. TouchableNativeFeedback is broken too. @cortinico this does not seem a duplicated as borderless is not in this scenario.

  11. cdamioli commented on Oct 24, 2025

    @cdamioli

    Probably the same issue than #53849

  12. taejinii commented on Oct 27, 2025

    @taejinii

    +1

  13. exist08 commented on Nov 17, 2025

    @exist08

    When this gonna be fixed ?

  14. kwikenkwak commented on Nov 20, 2025

    @kwikenkwak

    +1

  15. Palloxin commented on Nov 21, 2025

    @Palloxin

    Hope it gets fixed for 0.81 too

  16. Joshua-Herbert088 commented on Nov 24, 2025

    @Joshua-Herbert088

    +1

  17. mhmadamrii commented on Jan 8, 2026

    @mhmadamrii

    +1

  18. digvattul commented on Feb 2, 2026

    @digvattul

    +1

  19. Thereallo1026 commented on Feb 5, 2026

    @Thereallo1026

    In React Native 0.80, the enableNewBackgroundAndBorderDrawables feature flag was enabled by default. However, the setFeedbackUnderlay function has a bug in the feature-flagged code path:

    // BackgroundStyleApplicator.kt (v0.80.x - v0.82.x)
    public fun setFeedbackUnderlay(view: View, drawable: Drawable?): Unit {
        if (ReactNativeFeatureFlags.enableNewBackgroundAndBorderDrawables()) {
          // result gets discarded
          ensureCompositeBackgroundDrawable(view).withNewFeedbackUnderlay(drawable)
        } else {
          // correct: assigns to view.background
          view.background = ensureCompositeBackgroundDrawable(view).withNewFeedbackUnderlay(drawable)
        }
      }

    When enableNewBackgroundAndBorderDrawables() returns true, the code creates a new CompositeBackgroundDrawable with the ripple drawable via withNewFeedbackUnderlay(), but it never gets assigned to view.background.
    The ripple drawable is created and immediately garbage collected.

    The foreground ripple works because it uses view.foreground directly in ReactViewManager.kt, bypassing setFeedbackUnderlay:

    @ReactProp(name = "nativeForegroundAndroid")
    public open fun setNativeForeground(view: ReactViewGroup, foreground: ReadableMap?) {
        view.foreground = foreground?.let { ReactDrawableHelper.createDrawableFromJSDescription(view.context, it) }
    }

    This was fixed in commit e1071ce6837 (PR #53534) which removed the feature flag branch entirely:

    public fun setFeedbackUnderlay(view: View, drawable: Drawable?) {
        view.background = ensureCompositeBackgroundDrawable(view).withNewFeedbackUnderlay(drawable)
    }
  20. plahteenlahti commented on Feb 25, 2026

    @plahteenlahti

    I made a patch based on the above comment by Thereallo1026 for Expo 54, but turns out easiest way is to use just use Buttons from react-native-gesture-handler.

  21. marcshilling commented on May 11, 2026

    @marcshilling

    In React Native 0.80, the enableNewBackgroundAndBorderDrawables feature flag was enabled by default. However, the setFeedbackUnderlay function has a bug in the feature-flagged code path:

    // BackgroundStyleApplicator.kt (v0.80.x - v0.82.x)
    public fun setFeedbackUnderlay(view: View, drawable: Drawable?): Unit {
    if (ReactNativeFeatureFlags.enableNewBackgroundAndBorderDrawables()) {
    // result gets discarded
    ensureCompositeBackgroundDrawable(view).withNewFeedbackUnderlay(drawable)
    } else {
    // correct: assigns to view.background
    view.background = ensureCompositeBackgroundDrawable(view).withNewFeedbackUnderlay(drawable)
    }
    }
    When enableNewBackgroundAndBorderDrawables() returns true, the code creates a new CompositeBackgroundDrawable with the ripple drawable via withNewFeedbackUnderlay(), but it never gets assigned to view.background. The ripple drawable is created and immediately garbage collected.

    The foreground ripple works because it uses view.foreground directly in ReactViewManager.kt, bypassing setFeedbackUnderlay:

    @ReactProp(name = "nativeForegroundAndroid")
    public open fun setNativeForeground(view: ReactViewGroup, foreground: ReadableMap?) {
    view.foreground = foreground?.let { ReactDrawableHelper.createDrawableFromJSDescription(view.context, it) }
    }
    This was fixed in commit e1071ce6837 (PR #53534) which removed the feature flag branch entirely:

    public fun setFeedbackUnderlay(view: View, drawable: Drawable?) {
    view.background = ensureCompositeBackgroundDrawable(view).withNewFeedbackUnderlay(drawable)
    }

    Patching in this change to assign to view.background didn't work for me unfortunately on RN 0.81.5 new arch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions