Skip to content

Commit cfa4260

Browse files
IjzerenHeinfacebook-github-bot
authored andcommitted
Add support for shadowColor on Android (API >= 28) (#28650)
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
1 parent e96f1e1 commit cfa4260

File tree

8 files changed

+120
-2
lines changed

8 files changed

+120
-2
lines changed

Libraries/StyleSheet/StyleSheetTypes.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,9 @@ type ____TransformStyle_Internal = $ReadOnly<{|
522522
* Because they are dynamically generated, they may cause performance regressions. Static
523523
* shadow image asset may be a better way to go for optimal performance.
524524
*
525-
* These properties are iOS only - for similar functionality on Android, use the [`elevation`
526-
* property](docs/viewstyleproptypes.html#elevation).
525+
* Shadow-related properties are not fully supported on Android.
526+
* To add a drop shadow to a view use the [`elevation` property](docs/viewstyleproptypes.html#elevation) (Android 5.0+).
527+
* To customize the color use the [`shadowColor` property](docs/shadow-props.html#shadowColor) (Android 9.0+).
527528
*/
528529
export type ____ShadowStyle_Internal = $ReadOnly<{|
529530
/**

RNTester/js/examples/BoxShadow/BoxShadowExample.js

+94
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,29 @@ const styles = StyleSheet.create({
4646
margin: 8,
4747
backgroundColor: 'red',
4848
},
49+
50+
elevation1: {
51+
elevation: 1,
52+
},
53+
elevation2: {
54+
elevation: 3,
55+
},
56+
elevation3: {
57+
elevation: 10,
58+
},
59+
shadowColor1: {
60+
shadowColor: 'red',
61+
},
62+
shadowColor2: {
63+
shadowColor: 'blue',
64+
},
65+
shadowColor3: {
66+
shadowColor: '#00FF0080',
67+
},
68+
border: {
69+
borderWidth: 5,
70+
borderColor: '#EEE',
71+
},
4972
});
5073

5174
exports.title = 'Box Shadow';
@@ -97,4 +120,75 @@ exports.examples = [
97120
);
98121
},
99122
},
123+
124+
{
125+
title: 'Basic elevation',
126+
description: 'elevation: 1, 3, 6',
127+
platform: 'android',
128+
render() {
129+
return (
130+
<View style={styles.wrapper}>
131+
<View style={[styles.box, styles.elevation1]} />
132+
<View style={[styles.box, styles.elevation2]} />
133+
<View style={[styles.box, styles.elevation3]} />
134+
</View>
135+
);
136+
},
137+
},
138+
{
139+
title: 'Fractional elevation',
140+
description: 'elevation: 0.1, 0.5, 1.5',
141+
platform: 'android',
142+
render() {
143+
return (
144+
<View style={styles.wrapper}>
145+
<View style={[styles.box, {elevation: 0.1}]} />
146+
<View style={[styles.box, {elevation: 0.5}]} />
147+
<View style={[styles.box, {elevation: 1.5}]} />
148+
</View>
149+
);
150+
},
151+
},
152+
{
153+
title: 'Colored shadow',
154+
description: "shadowColor: 'red', 'blue', '#00FF0080'",
155+
platform: 'android',
156+
render() {
157+
return (
158+
<View style={styles.wrapper}>
159+
<View style={[styles.box, styles.elevation1, styles.shadowColor1]} />
160+
<View style={[styles.box, styles.elevation2, styles.shadowColor2]} />
161+
<View style={[styles.box, styles.elevation3, styles.shadowColor3]} />
162+
</View>
163+
);
164+
},
165+
},
166+
{
167+
title: 'Shaped shadow',
168+
description: 'borderRadius: 50',
169+
platform: 'android',
170+
render() {
171+
return (
172+
<View style={styles.wrapper}>
173+
<View style={[styles.box, styles.elevation1, styles.shadowShaped]} />
174+
<View style={[styles.box, styles.elevation2, styles.shadowShaped]} />
175+
<View style={[styles.box, styles.elevation3, styles.shadowShaped]} />
176+
</View>
177+
);
178+
},
179+
},
180+
{
181+
title: 'Borders',
182+
description: 'borderWidth: 5',
183+
platform: 'android',
184+
render() {
185+
return (
186+
<View style={styles.wrapper}>
187+
<View style={[styles.box, styles.elevation1, styles.border]} />
188+
<View style={[styles.box, styles.elevation2, styles.border]} />
189+
<View style={[styles.box, styles.elevation3, styles.border]} />
190+
</View>
191+
);
192+
},
193+
},
100194
];

RNTester/js/utils/RNTesterList.android.js

+4
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ const APIExamples: Array<RNTesterExample> = [
144144
key: 'BorderExample',
145145
module: require('../examples/Border/BorderExample'),
146146
},
147+
{
148+
key: 'BoxShadowExample',
149+
module: require('../examples/BoxShadow/BoxShadowExample'),
150+
},
147151
{
148152
key: 'ClipboardExample',
149153
module: require('../examples/Clipboard/ClipboardExample'),

ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManager.java

+9
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@ public void setElevation(@NonNull T view, float elevation) {
9595
ViewCompat.setElevation(view, PixelUtil.toPixelFromDIP(elevation));
9696
}
9797

98+
@Override
99+
@ReactProp(name = ViewProps.SHADOW_COLOR, defaultInt = Color.BLACK, customType = "Color")
100+
public void setShadowColor(@NonNull T view, int shadowColor) {
101+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
102+
view.setOutlineAmbientShadowColor(shadowColor);
103+
view.setOutlineSpotShadowColor(shadowColor);
104+
}
105+
}
106+
98107
@Override
99108
@ReactProp(name = ViewProps.Z_INDEX)
100109
public void setZIndex(@NonNull T view, float zIndex) {

ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerAdapter.java

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ public void setBorderTopRightRadius(@NonNull T view, float borderRadius) {}
5454
@Override
5555
public void setElevation(@NonNull T view, float elevation) {}
5656

57+
@Override
58+
public void setShadowColor(@NonNull T view, int shadowColor) {}
59+
5760
@Override
5861
public void setImportantForAccessibility(
5962
@NonNull T view, @Nullable String importantForAccessibility) {}

ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerDelegate.java

+4
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ public void setProperty(T view, String propName, @Nullable Object value) {
7474
case ViewProps.ELEVATION:
7575
mViewManager.setElevation(view, value == null ? 0.0f : ((Double) value).floatValue());
7676
break;
77+
case ViewProps.SHADOW_COLOR:
78+
mViewManager.setShadowColor(
79+
view, value == null ? 0 : ColorPropConverter.getColor(value, view.getContext()));
80+
break;
7781
case ViewProps.IMPORTANT_FOR_ACCESSIBILITY:
7882
mViewManager.setImportantForAccessibility(view, (String) value);
7983
break;

ReactAndroid/src/main/java/com/facebook/react/uimanager/BaseViewManagerInterface.java

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public interface BaseViewManagerInterface<T extends View> {
4343

4444
void setElevation(T view, float elevation);
4545

46+
void setShadowColor(T view, int shadowColor);
47+
4648
void setImportantForAccessibility(T view, @Nullable String importantForAccessibility);
4749

4850
void setNativeId(T view, @Nullable String nativeId);

ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ public class ViewProps {
140140

141141
public static final String TRANSFORM = "transform";
142142
public static final String ELEVATION = "elevation";
143+
public static final String SHADOW_COLOR = "shadowColor";
143144
public static final String Z_INDEX = "zIndex";
144145
public static final String RENDER_TO_HARDWARE_TEXTURE = "renderToHardwareTextureAndroid";
145146
public static final String ACCESSIBILITY_LABEL = "accessibilityLabel";

0 commit comments

Comments
 (0)