diff --git a/Libraries/Components/View/ViewStylePropTypes.js b/Libraries/Components/View/ViewStylePropTypes.js index e36b143a1..9f7ba776a 100644 --- a/Libraries/Components/View/ViewStylePropTypes.js +++ b/Libraries/Components/View/ViewStylePropTypes.js @@ -47,6 +47,14 @@ var ViewStylePropTypes = { ), shadowOpacity: ReactPropTypes.number, shadowRadius: ReactPropTypes.number, + /** + * (Android-only) Sets the elevation of a view, using Android's underlying + * [elevation API](https://developer.android.com/training/material/shadows-clipping.html#Elevation). + * This adds a drop shadow to the item and affects z-order for overlapping views. + * Only supported on Android 5.0+, has no effect on earlier versions. + * @platform android + */ + elevation: ReactPropTypes.number, }; module.exports = ViewStylePropTypes; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java index 84289b62d..4a8805614 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java @@ -17,12 +17,14 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.DashPathEffect; +import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PathEffect; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; +import android.os.Build; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.csslayout.CSSConstants; @@ -123,6 +125,23 @@ import com.facebook.csslayout.Spacing; return ColorUtil.getOpacityFromColor(ColorUtil.multiplyColorAlpha(mColor, mAlpha)); } + /* Android's elevation implementation requires this to be implemented to know where to draw the shadow. */ + @Override + public void getOutline(Outline outline) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + super.getOutline(outline); + return; + } + if(!CSSConstants.isUndefined(mBorderRadius) && mBorderRadius > 0) { + float extraRadiusFromBorderWidth = (mBorderWidth != null) + ? mBorderWidth.get(Spacing.ALL) / 2f + : 0; + outline.setRoundRect(getBounds(), mBorderRadius + extraRadiusFromBorderWidth); + } else { + super.getOutline(outline); + } + } + public void setBorderWidth(int position, float width) { if (mBorderWidth == null) { mBorderWidth = new Spacing(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index ac0dfee0f..6e002fb9f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -64,6 +64,14 @@ public class ReactViewManager extends ViewGroupManager { view.setBorderStyle(borderStyle); } + @ReactProp(name = "elevation") + public void setElevation(ReactViewGroup view, float elevation) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + view.setElevation(PixelUtil.toPixelFromDIP(elevation)); + } + // Do nothing on API < 21 + } + @ReactProp(name = "pointerEvents") public void setPointerEvents(ReactViewGroup view, @Nullable String pointerEventsStr) { if (pointerEventsStr != null) {