Skip to content

Commit

Permalink
Add support for shadowColor on Android (API >= 28) (#28650)
Browse files Browse the repository at this point in the history
Summary:
This PR adds support for the `shadowColor` style on Android.

This is possible as of Android P using the `setOutlineAmbientShadowColor` and `setOutlineSpotShadowColor` View methods. The actual rendered color is a multiplication of the color-alpha, shadow-effect and elevation-value.

## Changelog

`[Android] [Added] - Add support for shadowColor on API level >= 28`
Pull Request resolved: #28650

Test Plan:
- Only execute code on Android P
- Added Android `BoxShadow` tests to RNTester app

![image](https://user-images.githubusercontent.com/6184593/79457137-fe627c80-7fef-11ea-8e88-3d9423a4f264.png)

Reviewed By: mdvacca

Differential Revision: D21125479

Pulled By: shergin

fbshipit-source-id: 14dcc023977d7a9d304fabcd3c90bcf34482f137
  • Loading branch information
IjzerenHein authored and facebook-github-bot committed Jul 8, 2020
1 parent e96f1e1 commit cfa4260
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 2 deletions.
5 changes: 3 additions & 2 deletions Libraries/StyleSheet/StyleSheetTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,9 @@ type ____TransformStyle_Internal = $ReadOnly<{|
* Because they are dynamically generated, they may cause performance regressions. Static
* shadow image asset may be a better way to go for optimal performance.
*
* These properties are iOS only - for similar functionality on Android, use the [`elevation`
* property](docs/viewstyleproptypes.html#elevation).
* Shadow-related properties are not fully supported on Android.
* To add a drop shadow to a view use the [`elevation` property](docs/viewstyleproptypes.html#elevation) (Android 5.0+).
* To customize the color use the [`shadowColor` property](docs/shadow-props.html#shadowColor) (Android 9.0+).
*/
export type ____ShadowStyle_Internal = $ReadOnly<{|
/**
Expand Down
94 changes: 94 additions & 0 deletions RNTester/js/examples/BoxShadow/BoxShadowExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,29 @@ const styles = StyleSheet.create({
margin: 8,
backgroundColor: 'red',
},

elevation1: {
elevation: 1,
},
elevation2: {
elevation: 3,
},
elevation3: {
elevation: 10,
},
shadowColor1: {
shadowColor: 'red',
},
shadowColor2: {
shadowColor: 'blue',
},
shadowColor3: {
shadowColor: '#00FF0080',
},
border: {
borderWidth: 5,
borderColor: '#EEE',
},
});

exports.title = 'Box Shadow';
Expand Down Expand Up @@ -97,4 +120,75 @@ exports.examples = [
);
},
},

{
title: 'Basic elevation',
description: 'elevation: 1, 3, 6',
platform: 'android',
render() {
return (
<View style={styles.wrapper}>
<View style={[styles.box, styles.elevation1]} />
<View style={[styles.box, styles.elevation2]} />
<View style={[styles.box, styles.elevation3]} />
</View>
);
},
},
{
title: 'Fractional elevation',
description: 'elevation: 0.1, 0.5, 1.5',
platform: 'android',
render() {
return (
<View style={styles.wrapper}>
<View style={[styles.box, {elevation: 0.1}]} />
<View style={[styles.box, {elevation: 0.5}]} />
<View style={[styles.box, {elevation: 1.5}]} />
</View>
);
},
},
{
title: 'Colored shadow',
description: "shadowColor: 'red', 'blue', '#00FF0080'",
platform: 'android',
render() {
return (
<View style={styles.wrapper}>
<View style={[styles.box, styles.elevation1, styles.shadowColor1]} />
<View style={[styles.box, styles.elevation2, styles.shadowColor2]} />
<View style={[styles.box, styles.elevation3, styles.shadowColor3]} />
</View>
);
},
},
{
title: 'Shaped shadow',
description: 'borderRadius: 50',
platform: 'android',
render() {
return (
<View style={styles.wrapper}>
<View style={[styles.box, styles.elevation1, styles.shadowShaped]} />
<View style={[styles.box, styles.elevation2, styles.shadowShaped]} />
<View style={[styles.box, styles.elevation3, styles.shadowShaped]} />
</View>
);
},
},
{
title: 'Borders',
description: 'borderWidth: 5',
platform: 'android',
render() {
return (
<View style={styles.wrapper}>
<View style={[styles.box, styles.elevation1, styles.border]} />
<View style={[styles.box, styles.elevation2, styles.border]} />
<View style={[styles.box, styles.elevation3, styles.border]} />
</View>
);
},
},
];
4 changes: 4 additions & 0 deletions RNTester/js/utils/RNTesterList.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ const APIExamples: Array<RNTesterExample> = [
key: 'BorderExample',
module: require('../examples/Border/BorderExample'),
},
{
key: 'BoxShadowExample',
module: require('../examples/BoxShadow/BoxShadowExample'),
},
{
key: 'ClipboardExample',
module: require('../examples/Clipboard/ClipboardExample'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ public void setElevation(@NonNull T view, float elevation) {
ViewCompat.setElevation(view, PixelUtil.toPixelFromDIP(elevation));
}

@Override
@ReactProp(name = ViewProps.SHADOW_COLOR, defaultInt = Color.BLACK, customType = "Color")
public void setShadowColor(@NonNull T view, int shadowColor) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
view.setOutlineAmbientShadowColor(shadowColor);
view.setOutlineSpotShadowColor(shadowColor);
}
}

@Override
@ReactProp(name = ViewProps.Z_INDEX)
public void setZIndex(@NonNull T view, float zIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ public void setBorderTopRightRadius(@NonNull T view, float borderRadius) {}
@Override
public void setElevation(@NonNull T view, float elevation) {}

@Override
public void setShadowColor(@NonNull T view, int shadowColor) {}

@Override
public void setImportantForAccessibility(
@NonNull T view, @Nullable String importantForAccessibility) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ public void setProperty(T view, String propName, @Nullable Object value) {
case ViewProps.ELEVATION:
mViewManager.setElevation(view, value == null ? 0.0f : ((Double) value).floatValue());
break;
case ViewProps.SHADOW_COLOR:
mViewManager.setShadowColor(
view, value == null ? 0 : ColorPropConverter.getColor(value, view.getContext()));
break;
case ViewProps.IMPORTANT_FOR_ACCESSIBILITY:
mViewManager.setImportantForAccessibility(view, (String) value);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public interface BaseViewManagerInterface<T extends View> {

void setElevation(T view, float elevation);

void setShadowColor(T view, int shadowColor);

void setImportantForAccessibility(T view, @Nullable String importantForAccessibility);

void setNativeId(T view, @Nullable String nativeId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ public class ViewProps {

public static final String TRANSFORM = "transform";
public static final String ELEVATION = "elevation";
public static final String SHADOW_COLOR = "shadowColor";
public static final String Z_INDEX = "zIndex";
public static final String RENDER_TO_HARDWARE_TEXTURE = "renderToHardwareTextureAndroid";
public static final String ACCESSIBILITY_LABEL = "accessibilityLabel";
Expand Down

0 comments on commit cfa4260

Please sign in to comment.