React-native: [Android] [Style] No box-shadows on Android

Created on 16 Sep 2015  Â·  29Comments  Â·  Source: facebook/react-native

I might totally be missing something but shadows don't appear on my android phone (and they do the iOS simulator). Here's the style:

<View style={{
  width: 320,
  margin: 8,
  borderRadius: 2,
  shadowOffset: {
    width: 0,
    height: 1,
  },
  shadowRadius: 2,
  shadowOpacity: 0.2,
  shadowColor: 'black',
  backgroundColor: '#fff',
}}>
  <View style={{
    flexDirection: 'row',
    height: 48,
  }}>
    <View style={{
      justifyContent: 'center',
      flex: 1,
      paddingRight: 8,
      overflow: 'hidden',
    }}>
      <Text style={{
        fontFamily: 'Helvetica Neue',
        color: 'rgb(51, 51, 51)',
        fontSize: 14,
      }}>
        Lorem ipsum dolor sit amet, consectetur
      </Text>
    </View>
  </View>
</View>
Help Wanted Locked

Most helpful comment

I have implemented CardView for react-native with elevation, that support android(All version) and iOS. https://github.com/Kishanjvaghela/react-native-cardview

All 29 comments

We don't support shadows on Android currently. These are notoriously hard to implement as they require drawing outside of a view's bounds and Android's invalidation logic can't really deal with that.

Oh that's unfortunate, any plans on making it happen some time soon? :p

@bsansouci - I updated known issues to reflect this: https://github.com/facebook/react-native/commit/c1c455ff8a585e74492bb91191212f3de8de4cda :smile:

@brentvatne mentions we could try to use elevation or something similar (using outlines) to achieve this, but this would only work on Android 5.0+.

Considering I kind of need those nice shadows, I'll try to look into it (I'm not an android dev though so this might take some time :p)

@foghina (or any other Android gurus) -- do you know if it's possible to use the appcompat library to get the effects of elevation on Android 4.x? And if not, could we enable shadows on Android 5.0+ and have them gracefully not show up on Android 4.x so that the UI is nominally usable but not necessarily ideal?

@ide you could take a look at how AppCompat CardView does it.

CardView uses elevation property on L for shadows and falls back to a custom shadow implementation on older platforms. Before L, CardView adds padding to its content and draws shadows to that area.

Rather than drawing the shadow outside of the View's bounds, it automatically adds a bit of padding on Android < 5.0 and draws the shadow in that padded area using RoundRectDrawableWithShadow. Naturally, changing layout props like this is surprising behaviour and may not be appropriate for RN. But you could always just use View#setElevation() on Android 5.0+ and ignore older versions for now.

Modifying the elevation will change the radius and opacity of the shadow, but how would we change the offset?

At this point, even static shadows would greatly enhance the "native-ness" of the components.

++ Elevation for 5+

Would it be reasonable to add an "elevation" prop for views that (1) sets elevation for android 5+ (2) does nothing on Android <5 (current behavior for "elevation" in the appcompat packages if I'm not mistaken) and (3) sets shadows on iOS to mimic the "elevation" effect? This seems like the most straightforward (and perhaps only sane) way to implement cross-platform shadows across both Android and iOS without users having to write a bunch of platform-specific code.

@corbt I don't think it's a good idea to have different ways to describe shadows for View. There should be a way to make boxShadow and shadowOffset work with elevation and translationZ.

@bsansouci so the issue from my perspective is that Android doesn't give you a fine-grained way to set a shadow. Really the only levers you have to pull are elevation and translationZ (which are basically driving the same thing anyway, so you really only have _one_ independent dimension to play with). And I haven't seen any other shadow implementations on Android that can be used in a consistent, programmatic way. Given that state of affairs, I only see a few options:

  1. Don't support shadows on Android :(
  2. Add an Android-only elevation style for views that does nothing on iOS. So cross-platform views would need to set elevation as well as the shadow* APIs.
  3. Use some combination of the shadowRadius, shadowOffset and shadowOpacity to compute a value for elevation behind the scenes on Android. Remember though, we only get to set one number on Android, so some layout information will inevitably be lost here. (With this option it may just make sense to translate shadowRadius to an elevation and throw away the other two numbers on Android -- I think we have to throw away shadowColor anyway).
  4. Implement elevation as a cross-platform prop that invokes the elevation Android API for Android 5+, does nothing on Android < 5 and sets the shadow* APIs on iOS to create a visually similar effect.

Option (4) is what I proposed above. I totally agree that having multiple ways to set a shadow on a view isn't ideal, but I still think it's cleaner than having to set both elevation and shadow styles on any cross-platform view (option 2). Option 3, which I think is what you are suggesting, has merit as well. My concern is that since so much information is being thrown away anyway because of elevation's limitations, it might be better to encode it in a new style option so users understand what they're getting into. Reasonable minds may disagree.

On a more philosophical level, I actually like what Google is doing with the elevation property in material design. 99% of the time I use shadows, what I'm actually trying to convey is a sense of elevation/levels. Setting the offset/radius/opacity feel like the wrong level of abstraction for this use case. So I wouldn't mind just sticking with elevation across all platforms and letting the library calculate the brass tacks of how that's actually implemented.

Those are very good points. I didn't understand that translationZ + elevation didn't give us enough power to express all of the same shadows as on iOS. I actually think there are two other options: make a ShadowAndroid component that's just a View that has an elevation prop. I think this is a better option that than 2 because it doesn't make sense for RN to have a platform specific property on Views, and it's better than 4 because there isn't two way doing things (if you're using the same component for iOS and android you'd use boxShadow _and_ elevation which is confusing). Or the other option is have a top level property specific to android called elevation on Views. I'd argue this is a less good solution as it seems like most top level properties don't deal with visuals, they are behavior related.

@bsansouci RN already has platform specific properties for components. And if you think about it, boxShadow is a platform specific property right now as it works only on iOS, and not Android.

I'm kinda leaning towards 4. Most of the time I just want to convey a sense of elevation.

Creating another view component will increase the complexity greatly IMO. It's not ideal to subclass a view just because of one property. Other option is to have the property as androidElevation. But it has the problem that you will need to define both boxShadow and elevation if you want shadows both on iOS and Android. Not as clean.

@satya164 @corbt Ok, I think I agree with 4 after giving it some more thoughts.

Any updates on this issue? I tried using setElevation but my android development knowledge is far too limited to figure it out :cry:

If anyone could tell me how to set elevation on a certain component that'd be amazing :smile: And I can't wait for the elevation property to get implemented.

I tried to do this at some point but ran into some issues where setting elevation doesn't actually do anything, potentially due to our overriding of measurement and layout. I probably won't have time to look into this very soon. :disappointed:

@foghina OK if I mark this as Help Wanted to encourage experiments?

@ide good idea!

Ok I've had a chance to look into this and have some preliminary working code. I'll pull it together into a PR. @foghina it looks like elevation is working just fine in RN (at least in my basic tests); you may have been running into one of the limitations of Android's elevation attribute, the most prominent being that (1) it does nothing on Android < 5.0 and (2) it doesn't work for objects with a transparent or translucent background.

Ok, I've implemented elevation for React Native's View component in the PR above.

I have implemented CardView for react-native with elevation, that support android(All version) and iOS. https://github.com/Kishanjvaghela/react-native-cardview

As my experience, we can use Card with CardItem from native-base for shadow block.

for an android screen you can use this property elevation . for example --

HeaderView:{
    backgroundColor:'#F8F8F8',
    justifyContent:'center',
    alignItems:'center',
    height:60,
    paddingTop:15,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.2,
   // its for android 
    elevation: 5,
    position:'relative',

},

Elevation is not working for android 4.4

Elevation works only on Android 5.0 and above. Elevation was not
implemented on Android before that

On Mon, 25 Jun 2018, 8:48 pm ggepenyan, notifications@github.com wrote:

Elevation is not working for android 4.4

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/2768#issuecomment-399988548,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AHiF77JYwqP_Vk2h5h94w3-v2Dqb5_xgks5uAP9UgaJpZM4F-h5n
.

@NishanthShankar So what suggestions are to get shadow for android 4.4. It's not an issue?

None are great suggestions.
You could have a shadow image
Or you could use multiple borders with different grays wo give that effect

Again none are actual great suggestions

It is an issue but there is nothing much we can do about it

On Tue, 26 Jun 2018, 1:17 pm ggepenyan, notifications@github.com wrote:

@NishanthShankar https://github.com/NishanthShankar So what suggestions
are to get shadow for android 4.4. It's not an issue?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/react-native/issues/2768#issuecomment-400212798,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AHiF72szQGQ5UevYhxZjuy1Bi1E2u2Feks5uAecJgaJpZM4F-h5n
.

Was this page helpful?
0 / 5 - 0 ratings