Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elevation does not animate when it is inside a view which animates its opacity (Android P) #23090

Open
ferrannp opened this issue Jan 21, 2019 · 64 comments
Labels
Bug Help Wanted :octocat: Issues ideal for external contributors. Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Platform: Android Android applications. Ran Commands One of our bots successfully processed a command.

Comments

@ferrannp
Copy link
Contributor

ferrannp commented Jan 21, 2019

Environment

  React Native Environment Info:
    System:
      OS: macOS 10.14.1
      CPU: x64 Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
      Memory: 40.65 MB / 16.00 GB
      Shell: 5.6.2 - /usr/local/bin/zsh
    Binaries:
      Node: 10.11.0 - ~/.nvm/versions/node/v10.11.0/bin/node
      Yarn: 1.13.0 - ~/.nvm/versions/node/v10.11.0/bin/yarn
      npm: 6.5.0 - ~/.nvm/versions/node/v10.11.0/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    SDKs:
      iOS SDK:
        Platforms: iOS 11.4, macOS 10.13, tvOS 11.4, watchOS 4.3
      Android SDK:
        Build Tools: 23.0.1, 26.0.2, 26.0.3, 27.0.2, 27.0.3, 28.0.1, 28.0.2, 28.0.3
        API Levels: 22, 23, 24, 25, 26, 27, 28
    IDEs:
      Android Studio: 3.3 AI-182.5107.16.33.5199772
      Xcode: 9.4.1/9F2000 - /usr/bin/xcodebuild
    npmPackages:
      react: 16.6.3 => 16.6.3
      react-native: 0.59.0 => 0.59.0
    npmGlobalPackages:
      react-native-cli: 2.0.1

Description

What described in the title works in any Android but not on Android P. See the differences:

Android P:

androidp

Below Android P:

notandroidp

Reproducible Demo

https://snack.expo.io/@satya164/elevation-issue---android-p

This can affect libraries like react-navigation when a new screen comes in animating its opacity. See react-navigation/react-navigation#5535.

Can be found here also https://github.com/ferrannp/react-native-elevation-animation-android-pie with react-native 0.59.X.

@react-native-bot react-native-bot added the Platform: Android Android applications. label Jan 21, 2019
@brentvatne brentvatne changed the title [ANDROID] - Elevation does not animate when it is inside a view which animates its opacity (Android P) Elevation does not animate when it is inside a view which animates its opacity (Android P) Jan 24, 2019
@react-native-bot
Copy link
Collaborator

It looks like you are using an older version of React Native. Please update to the latest release, v0.58 and verify if the issue still exists.

The "⏪Old Version" label will be removed automatically once you edit your original post with the results of running react-native info on a project using the latest release.

@iremlopsum
Copy link

I've been running into the same issue for awhile now. Seems to be happening as well for 0.58.3.

@RichardLindhout
Copy link

+1

@react-native-bot
Copy link
Collaborator

I am closing this issue because it does not appear to have been verified on the latest release, and there has been no followup in a while.

If you found this thread after encountering the same issue in the latest release, please feel free to create a new issue with up-to-date information by clicking here.

@react-native-bot react-native-bot added the Ran Commands One of our bots successfully processed a command. label Feb 24, 2019
@alexandrius
Copy link

I experience this issue too

@ferrannp
Copy link
Contributor Author

I added a repo with react-native init that reproduces the issue https://github.com/ferrannp/react-native-elevation-animation-android-pie.

@kelset kelset added Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. and removed Resolution: Old Version labels Mar 12, 2019
@kelset kelset reopened this Mar 12, 2019
@kenlojt
Copy link

kenlojt commented Apr 1, 2019

Hi i'm experiencing this issue as well on Android Pie only (earlier versions are fine), any suggestions on work arounds?

@nismangulov
Copy link

I'm experiencing this issue too. Does anybody found a workaround for this issue?

@pratishshr
Copy link

pratishshr commented Apr 13, 2019

Is anyone working on this? We are facing the same issue

@tallen11
Copy link

tallen11 commented May 9, 2019

Also facing this issue, any solution?

@Ashkan-Oliaie
Copy link

damn this is bad, never thought it would be like that , for now I can't use elevation because it leave the shadow for a little while , when the opacity goes to 0

@palkerecsenyi
Copy link

I'm also facing this issue. Does anyone know any workaround? Especially annoying when I'm trying to animate a box with several buttons inside it, the shadows appear before the buttons do.

@iremlopsum
Copy link

iremlopsum commented Jul 9, 2020

@fabriziobertoglio1987 The child needs to have elevation.

<Animated.View style={{ opacity: animatedOpacityValue }}>
  <View style={{ width: 100, height: 100, backgroundColor: 'pink', elevation 5 }} />
</Animated.View>

This is the easiest way to reproduce

@mshafex
Copy link

mshafex commented Jul 15, 2020

happening on 0.62.2

@retyui
Copy link
Contributor

retyui commented Jul 16, 2020

happening on 0.63.1

image

@CyxouD
Copy link

CyxouD commented Jul 22, 2020

I experienced it a few times in different react-native version, also in react-native 63.0
What works for me is using react-native-shadow in such cases which creates fake SVG shadow 😎
Warning: it doesn't look the same as a native shadow, but in my opinion pretty good. Maybe use an original one for iOS and react-native-shadow for Android

For example

          <BoxShadow
            setting={{
              border: 2,
              color: '#000',
              height: 400,
              opacity: 0.25,
              radius: 10,
              width: Dimensions.get('window').width - 40,
              x: 0,
              y: 3,
            }}
          >
            <View
              style={{
                flex: 1,
                paddingHorizontal: 40,
                paddingVertical: 30,
                backgroundColor: 'white',
                borderRadius: 10,
              }}
            >
                  // your content
            </View>
          </BoxShadow>

This is how it looks eventually on Android:
image

@Return-1
Copy link

@CyxouD Thank you for the workaround, i will keep it in mind for when shadows are a necessity. It's such a pity, Neumorphism employs shadows a lot and i'm facing such a scenario but i will keep it in mind. The main issue is with react-navigation to be honest but what can you do : /

@sa8ab
Copy link

sa8ab commented Jul 23, 2020

@CyxouD I believe it can be edited in the setting prop so it looks more natural maybe even more than the elevation.

@DomiR
Copy link

DomiR commented Aug 5, 2020

My issue:
react-navigation/react-navigation#8676

On android, setting a view's opacity will render artifacts when child views have elevation.

So I've investigated this issue and came to the conclusion, that this is an android intended behavior.

Background:

<View style={{opacity: 0.5}}>
	<View style={{elevation: 5, margin: 10, backgroundColor: 'red'}}>
<View>

To understand this issue we let's dig into react code. Both views will get a BaseViewManager, which holds a reference to a ReactViewGroup.ReactViewGroup subclasses a ViewGroup and not an Android View (because it can have children). When setting a backgroundColor to a ReactViewGroup it creates a ReactViewBackgroundDrawable which subclasses a Drawable and sets it as background. The creation happens in getOrCreateReactViewBackground which composes any already existing background drawable (maybe images use this, in all my test cases the existing drawable was always null) with the new background using LayerDrawable.

Problem:
Now when setting an alpha value (changing opacity) it will do this on the ReactViewGroup directly but not on the background drawable, which is why we have the artifact. As react-native per default set hasOverlappingRendering to false to save memory, this problem is an expected android performance optimization. It seems that some devices do not perform the optimization and I only experienced this when changing the alpha after the first render. See android docs for what this flag does.

In the screenshot below you can see the different parameters (plain android project in this repo, not react-native, although I used the same ReactViewBackgroundDrawable class from react-native which I just extracted and patched to get it running).
There are 6 red 100x100 boxes that get the opacity set on their view or for testing purposes on their background drawable. Within a red box a yellow box is placed with elevation set to 10. In the first row, hasOverlappingRendering is disabled.

screenshot

Repo: https://github.com/DomiR/react-native-opacity-issue
So as you can see on both boxes on the right-hand side setting opacity only on the background is not enough, as all children will still have full opacity. Setting alpha both on the background and on the view itself will result in 0.25 opacity for the background. On the left-hand side is what we really want but we need to hasOverlappingRendering enabled like in the left bottom.

Solution:
I don't know if there is a solution that is good for everyone.
As you can see from the screenshot we need to set hasOverlappingRendering but doing so per default is not performant (facebook blog entry).

Fortunately, we can set this flag using needsOffscreenAlphaCompositing as a view prop.

As @kmagiera mentioned that you should probably enable this only temporarily during animations.
The react-native docs also mention using renderToHardwareTextureAndroid in combination.

PS: What also should work is setting the opacity value for all children as well.

@webgev
Copy link

webgev commented Oct 2, 2020

what about option "renderToHardwareTextureAndroid" for View?

@mmazzarolo
Copy link

Thanks @DomiR , can confirm that setting needsOffscreenAlphaCompositing on the animated view seems to solve the issue.

Before:
2020-10-17 12 19 34

After:
2020-10-17 12 19 07

PR example.

mmazzarolo added a commit to mmazzarolo/react-native-dialog that referenced this issue Oct 17, 2020
- Use two different animations for entering/exiting
- Removed useless styles
- Fix janky Android elevation animation by setting `needsOffscreenAlphaCompositing` while animating (see facebook/react-native#23090)
@retyui
Copy link
Contributor

retyui commented Mar 24, 2021

Any updates?

@suyogyabsnt
Copy link

So the trick is to set the elevation to 0 until fade-in animation is complete for the view.
elevation:fadeAnim==1?5:0
Work's perfectly for me.

PdoubleU added a commit to TheWidlarzGroup/react-native-notificated that referenced this issue Nov 3, 2023
PdoubleU added a commit to TheWidlarzGroup/react-native-notificated that referenced this issue Nov 3, 2023
PdoubleU added a commit to TheWidlarzGroup/react-native-notificated that referenced this issue Nov 20, 2023
…phaCompositing={true}) (#225)

* * fix shadow artifacts on Android (use needsOffscreenAlphaCompositing={true})
* ref: facebook/react-native#23090 (comment)

* * use needsOffscreenAlphaCompositing only on Android
@fabOnReact
Copy link
Contributor

fabOnReact commented Feb 2, 2024

Several users tested a workaround (needsOffscreenAlphaCompositing) for this issue (more info in #23090 (comment)). I believe this issue is solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Help Wanted :octocat: Issues ideal for external contributors. Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Platform: Android Android applications. Ran Commands One of our bots successfully processed a command.
Projects
None yet
Development

No branches or pull requests