diff --git a/packages/react-native/Libraries/Components/View/ViewNativeComponent.js b/packages/react-native/Libraries/Components/View/ViewNativeComponent.js index df119f6c5edf5d..a3cdea8a721a38 100644 --- a/packages/react-native/Libraries/Components/View/ViewNativeComponent.js +++ b/packages/react-native/Libraries/Components/View/ViewNativeComponent.js @@ -94,6 +94,9 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = borderBlockStartColor: { process: require('../../StyleSheet/processColor').default, }, + experimental_boxShadow: { + process: require('../../StyleSheet/processBoxShadow').default, + }, focusable: true, overflow: true, diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index ff4e2afa4acbcd..f96a609fbe7afc 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -4091,6 +4091,7 @@ public final class com/facebook/react/uimanager/BackgroundStyleApplicator { public static final fun setBorderWidth (Landroid/view/View;Lcom/facebook/react/uimanager/style/LogicalEdge;Ljava/lang/Float;)V public static final fun setBoxShadow (Landroid/view/View;Lcom/facebook/react/bridge/ReadableArray;)V public static final fun setBoxShadow (Landroid/view/View;Ljava/util/List;)V + public static final fun setFeedbackUnderlay (Landroid/view/View;Landroid/graphics/drawable/Drawable;)V } public abstract class com/facebook/react/uimanager/BaseViewManager : com/facebook/react/uimanager/ViewManager, android/view/View$OnLayoutChangeListener, com/facebook/react/uimanager/BaseViewManagerInterface { @@ -8195,7 +8196,6 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro public fun requestLayout ()V public fun setBackfaceVisibility (Ljava/lang/String;)V public fun setBackfaceVisibilityDependantOpacity ()V - public fun setBackground (Landroid/graphics/drawable/Drawable;)V public fun setBackgroundColor (I)V public fun setBorderColor (ILjava/lang/Integer;)V public fun setBorderRadius (F)V @@ -8234,11 +8234,14 @@ public class com/facebook/react/views/view/ReactViewManager : com/facebook/react public fun receiveCommand (Lcom/facebook/react/views/view/ReactViewGroup;Ljava/lang/String;Lcom/facebook/react/bridge/ReadableArray;)V public fun setAccessible (Lcom/facebook/react/views/view/ReactViewGroup;Z)V public fun setBackfaceVisibility (Lcom/facebook/react/views/view/ReactViewGroup;Ljava/lang/String;)V + public synthetic fun setBackgroundColor (Landroid/view/View;I)V + public fun setBackgroundColor (Lcom/facebook/react/views/view/ReactViewGroup;I)V public fun setBorderColor (Lcom/facebook/react/views/view/ReactViewGroup;ILjava/lang/Integer;)V public fun setBorderRadius (Lcom/facebook/react/views/view/ReactViewGroup;IF)V public fun setBorderRadius (Lcom/facebook/react/views/view/ReactViewGroup;ILcom/facebook/react/bridge/Dynamic;)V public fun setBorderStyle (Lcom/facebook/react/views/view/ReactViewGroup;Ljava/lang/String;)V public fun setBorderWidth (Lcom/facebook/react/views/view/ReactViewGroup;IF)V + public fun setBoxShadow (Lcom/facebook/react/views/view/ReactViewGroup;Lcom/facebook/react/bridge/ReadableArray;)V public fun setCollapsable (Lcom/facebook/react/views/view/ReactViewGroup;Z)V public fun setCollapsableChildren (Lcom/facebook/react/views/view/ReactViewGroup;Z)V public fun setFocusable (Lcom/facebook/react/views/view/ReactViewGroup;Z)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BackgroundStyleApplicator.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BackgroundStyleApplicator.kt index f0a8a631462251..ab423f18785074 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BackgroundStyleApplicator.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BackgroundStyleApplicator.kt @@ -10,6 +10,7 @@ package com.facebook.react.uimanager import android.graphics.Canvas import android.graphics.Color import android.graphics.Rect +import android.graphics.drawable.Drawable import android.os.Build import android.view.View import androidx.annotation.ColorInt @@ -149,6 +150,11 @@ public object BackgroundStyleApplicator { BackgroundStyleApplicator.setBoxShadow(view, shadowStyles) } + @JvmStatic + public fun setFeedbackUnderlay(view: View, drawable: Drawable?): Unit { + view.background = ensureCompositeBackgroundDrawable(view).withNewFeedbackUnderlay(drawable) + } + @JvmStatic public fun clipToPaddingBox(view: View, canvas: Canvas): Unit { // The canvas may be scrolled, so we need to offset diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt index 785c14fe935c43..cdf83e51fad64e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt @@ -34,11 +34,11 @@ internal class CompositeBackgroundDrawable( */ public val cssBackground: CSSBackgroundDrawable? = null, + /** TouchableNativeFeeback set selection background, like "SelectableBackground" */ + public val feedbackUnderlay: Drawable? = null, + /** Inset box-shadows */ public val innerShadows: List = emptyList(), - - /** Native riplple effect (e.g. used by TouchableNativeFeedback) */ - public val nativeRipple: Drawable? = null ) : LayerDrawable( listOfNotNull( @@ -48,8 +48,8 @@ internal class CompositeBackgroundDrawable( // https://drafts.csswg.org/css-backgrounds/#shadow-layers *outerShadows.asReversed().toTypedArray(), cssBackground, - *innerShadows.asReversed().toTypedArray(), - nativeRipple) + feedbackUnderlay, + *innerShadows.asReversed().toTypedArray()) .toTypedArray()) { init { @@ -63,7 +63,7 @@ internal class CompositeBackgroundDrawable( cssBackground: CSSBackgroundDrawable? ): CompositeBackgroundDrawable { return CompositeBackgroundDrawable( - originalBackground, outerShadows, cssBackground, innerShadows, nativeRipple) + originalBackground, outerShadows, cssBackground, feedbackUnderlay, innerShadows) } public fun withNewShadows( @@ -71,11 +71,11 @@ internal class CompositeBackgroundDrawable( innerShadows: List ): CompositeBackgroundDrawable { return CompositeBackgroundDrawable( - originalBackground, outerShadows, cssBackground, innerShadows, nativeRipple) + originalBackground, outerShadows, cssBackground, feedbackUnderlay, innerShadows) } - public fun withNewNativeRipple(newRipple: Drawable?): CompositeBackgroundDrawable { + public fun withNewFeedbackUnderlay(newUnderlay: Drawable?): CompositeBackgroundDrawable { return CompositeBackgroundDrawable( - originalBackground, outerShadows, cssBackground, innerShadows, newRipple) + originalBackground, outerShadows, cssBackground, newUnderlay, innerShadows) } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 31ed523bdd261f..c1218f26c70932 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -37,9 +37,12 @@ import com.facebook.react.touch.OnInterceptTouchEventListener; import com.facebook.react.touch.ReactHitSlopView; import com.facebook.react.touch.ReactInterceptingViewGroup; +import com.facebook.react.uimanager.BackgroundStyleApplicator; import com.facebook.react.uimanager.IllegalViewOperationException; import com.facebook.react.uimanager.LengthPercentage; +import com.facebook.react.uimanager.LengthPercentageType; import com.facebook.react.uimanager.MeasureSpecAssertions; +import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.PointerEvents; import com.facebook.react.uimanager.ReactClippingProhibitedView; import com.facebook.react.uimanager.ReactClippingViewGroup; @@ -50,12 +53,14 @@ import com.facebook.react.uimanager.RootView; import com.facebook.react.uimanager.RootViewUtil; import com.facebook.react.uimanager.ViewGroupDrawingOrderHelper; -import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.common.ViewUtil; import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable; import com.facebook.react.uimanager.style.BorderRadiusProp; +import com.facebook.react.uimanager.style.BorderStyle; import com.facebook.react.uimanager.style.ComputedBorderRadius; +import com.facebook.react.uimanager.style.LogicalEdge; +import com.facebook.react.uimanager.style.Overflow; /** * Backing for a React View. Has support for borders, but since borders aren't common, lazy @@ -122,7 +127,7 @@ public void onLayoutChange( private int mAllChildrenCount; private @Nullable Rect mClippingRect; private @Nullable Rect mHitSlopRect; - private @Nullable String mOverflow; + private Overflow mOverflow; private PointerEvents mPointerEvents; private @Nullable ChildrenLayoutChangeListener mChildrenLayoutChangeListener; private @Nullable CSSBackgroundDrawable mCSSBackgroundDrawable; @@ -151,7 +156,7 @@ private void initView() { mAllChildrenCount = 0; mClippingRect = null; mHitSlopRect = null; - mOverflow = null; + mOverflow = Overflow.VISIBLE; mPointerEvents = PointerEvents.AUTO; mChildrenLayoutChangeListener = null; mCSSBackgroundDrawable = null; @@ -217,31 +222,34 @@ public void dispatchProvideStructure(ViewStructure structure) { @Override public void setBackgroundColor(int color) { - if (color == Color.TRANSPARENT && mCSSBackgroundDrawable == null) { - // don't do anything, no need to allocate ReactBackgroundDrawable for transparent background + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBackgroundColor(this, color); } else { - getOrCreateReactViewBackground().setColor(color); + if (color == Color.TRANSPARENT && mCSSBackgroundDrawable == null) { + // don't do anything, no need to allocate ReactBackgroundDrawable for transparent background + } else { + getOrCreateReactViewBackground().setColor(color); + } } } - @Override - public void setBackground(Drawable drawable) { - throw new UnsupportedOperationException( - "This method is not supported for ReactViewGroup instances"); - } - + @Deprecated(since = "0.66.0", forRemoval = true) public void setTranslucentBackgroundDrawable(@Nullable Drawable background) { - // it's required to call setBackground to null, as in some of the cases we may set new - // background to be a layer drawable that contains a drawable that has been setup - // as a background previously. This will not work correctly as the drawable callback logic is - // messed up in AOSP - updateBackgroundDrawable(null); - if (mCSSBackgroundDrawable != null && background != null) { - LayerDrawable layerDrawable = - new LayerDrawable(new Drawable[] {mCSSBackgroundDrawable, background}); - updateBackgroundDrawable(layerDrawable); - } else if (background != null) { - updateBackgroundDrawable(background); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setFeedbackUnderlay(this, background); + } else { + // it's required to call setBackground to null, as in some of the cases we may set new + // background to be a layer drawable that contains a drawable that has been setup + // as a background previously. This will not work correctly as the drawable callback logic is + // messed up in AOSP + updateBackgroundDrawable(null); + if (mCSSBackgroundDrawable != null && background != null) { + LayerDrawable layerDrawable = + new LayerDrawable(new Drawable[] {mCSSBackgroundDrawable, background}); + updateBackgroundDrawable(layerDrawable); + } else if (background != null) { + updateBackgroundDrawable(background); + } } } @@ -302,11 +310,20 @@ public void setNeedsOffscreenAlphaCompositing(boolean needsOffscreenAlphaComposi } public void setBorderWidth(int position, float width) { - getOrCreateReactViewBackground().setBorderWidth(position, width); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBorderWidth( + this, LogicalEdge.values()[position], PixelUtil.toDIPFromPixel(width)); + } else { + getOrCreateReactViewBackground().setBorderWidth(position, width); + } } public void setBorderColor(int position, @Nullable Integer color) { - getOrCreateReactViewBackground().setBorderColor(position, color); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBorderColor(this, LogicalEdge.values()[position], color); + } else { + getOrCreateReactViewBackground().setBorderColor(position, color); + } } /** @@ -314,8 +331,7 @@ public void setBorderColor(int position, @Nullable Integer color) { */ @Deprecated(since = "0.75.0", forRemoval = true) public void setBorderRadius(float borderRadius) { - CSSBackgroundDrawable backgroundDrawable = getOrCreateReactViewBackground(); - backgroundDrawable.setRadius(borderRadius); + setBorderRadius(borderRadius, BorderRadiusProp.BORDER_RADIUS.ordinal()); } /** @@ -323,17 +339,34 @@ public void setBorderRadius(float borderRadius) { */ @Deprecated(since = "0.75.0", forRemoval = true) public void setBorderRadius(float borderRadius, int position) { - CSSBackgroundDrawable backgroundDrawable = getOrCreateReactViewBackground(); - backgroundDrawable.setRadius(borderRadius, position); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + @Nullable + LengthPercentage radius = + Float.isNaN(borderRadius) + ? null + : new LengthPercentage(borderRadius, LengthPercentageType.POINT); + BackgroundStyleApplicator.setBorderRadius(this, BorderRadiusProp.values()[position], radius); + } else { + getOrCreateReactViewBackground().setRadius(borderRadius, position); + } } public void setBorderRadius(BorderRadiusProp property, @Nullable LengthPercentage borderRadius) { - CSSBackgroundDrawable backgroundDrawable = getOrCreateReactViewBackground(); - backgroundDrawable.setBorderRadius(property, borderRadius); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBorderRadius(this, property, borderRadius); + } else { + CSSBackgroundDrawable backgroundDrawable = getOrCreateReactViewBackground(); + backgroundDrawable.setBorderRadius(property, borderRadius); + } } public void setBorderStyle(@Nullable String style) { - getOrCreateReactViewBackground().setBorderStyle(style); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBorderStyle( + this, style == null ? null : BorderStyle.fromString(style)); + } else { + getOrCreateReactViewBackground().setBorderStyle(style); + } } @Override @@ -780,10 +813,15 @@ private void removeFromArray(int index) { @VisibleForTesting public int getBackgroundColor() { - if (getBackground() != null) { - return ((ReactViewBackgroundDrawable) getBackground()).getColor(); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + @Nullable Integer color = BackgroundStyleApplicator.getBackgroundColor(this); + return color == null ? DEFAULT_BACKGROUND_COLOR : color; + } else { + if (getBackground() != null) { + return ((CSSBackgroundDrawable) getBackground()).getColor(); + } + return DEFAULT_BACKGROUND_COLOR; } - return DEFAULT_BACKGROUND_COLOR; } /* package */ CSSBackgroundDrawable getOrCreateReactViewBackground() { @@ -819,14 +857,23 @@ public void setHitSlopRect(@Nullable Rect rect) { mHitSlopRect = rect; } - public void setOverflow(String overflow) { - mOverflow = overflow; + public void setOverflow(@Nullable String overflow) { + mOverflow = overflow == null ? Overflow.VISIBLE : Overflow.fromString(overflow); invalidate(); } @Override public @Nullable String getOverflow() { - return mOverflow; + switch (mOverflow) { + case HIDDEN: + return "hidden"; + case SCROLL: + return "scroll"; + case VISIBLE: + return "visible"; + } + + return null; } @Override @@ -852,6 +899,14 @@ public Rect getOverflowInset() { @Override protected void dispatchDraw(Canvas canvas) { + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + if (mOverflow != Overflow.VISIBLE) { + BackgroundStyleApplicator.clipToPaddingBox(this, canvas); + } + super.dispatchDraw(canvas); + return; + } + try { dispatchOverflowDraw(canvas); super.dispatchDraw(canvas); @@ -890,69 +945,67 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { } private void dispatchOverflowDraw(Canvas canvas) { - if (mOverflow != null) { - switch (mOverflow) { - case ViewProps.VISIBLE: - if (mPath != null) { - mPath.rewind(); + switch (mOverflow) { + case VISIBLE: + if (mPath != null) { + mPath.rewind(); + } + break; + case HIDDEN: + case SCROLL: + float left = 0f; + float top = 0f; + float right = getWidth(); + float bottom = getHeight(); + + boolean hasClipPath = false; + + if (mCSSBackgroundDrawable != null) { + final RectF borderWidth = mCSSBackgroundDrawable.getDirectionAwareBorderInsets(); + + if (borderWidth.top > 0 + || borderWidth.left > 0 + || borderWidth.bottom > 0 + || borderWidth.right > 0) { + left += borderWidth.left; + top += borderWidth.top; + right -= borderWidth.right; + bottom -= borderWidth.bottom; } - break; - case ViewProps.HIDDEN: - case ViewProps.SCROLL: - float left = 0f; - float top = 0f; - float right = getWidth(); - float bottom = getHeight(); - - boolean hasClipPath = false; - - if (mCSSBackgroundDrawable != null) { - final RectF borderWidth = mCSSBackgroundDrawable.getDirectionAwareBorderInsets(); - - if (borderWidth.top > 0 - || borderWidth.left > 0 - || borderWidth.bottom > 0 - || borderWidth.right > 0) { - left += borderWidth.left; - top += borderWidth.top; - right -= borderWidth.right; - bottom -= borderWidth.bottom; - } - final ComputedBorderRadius borderRadius = - mCSSBackgroundDrawable.getComputedBorderRadius(); + final ComputedBorderRadius borderRadius = + mCSSBackgroundDrawable.getComputedBorderRadius(); - if (borderRadius.hasRoundedBorders()) { - if (mPath == null) { - mPath = new Path(); - } - - mPath.rewind(); - mPath.addRoundRect( - new RectF(left, top, right, bottom), - new float[] { - Math.max(borderRadius.getTopLeft() - borderWidth.left, 0), - Math.max(borderRadius.getTopLeft() - borderWidth.top, 0), - Math.max(borderRadius.getTopRight() - borderWidth.right, 0), - Math.max(borderRadius.getTopRight() - borderWidth.top, 0), - Math.max(borderRadius.getBottomRight() - borderWidth.right, 0), - Math.max(borderRadius.getBottomRight() - borderWidth.bottom, 0), - Math.max(borderRadius.getBottomLeft() - borderWidth.left, 0), - Math.max(borderRadius.getBottomLeft() - borderWidth.bottom, 0), - }, - Path.Direction.CW); - canvas.clipPath(mPath); - hasClipPath = true; + if (borderRadius.hasRoundedBorders()) { + if (mPath == null) { + mPath = new Path(); } - } - if (!hasClipPath) { - canvas.clipRect(new RectF(left, top, right, bottom)); + mPath.rewind(); + mPath.addRoundRect( + new RectF(left, top, right, bottom), + new float[] { + Math.max(borderRadius.getTopLeft() - borderWidth.left, 0), + Math.max(borderRadius.getTopLeft() - borderWidth.top, 0), + Math.max(borderRadius.getTopRight() - borderWidth.right, 0), + Math.max(borderRadius.getTopRight() - borderWidth.top, 0), + Math.max(borderRadius.getBottomRight() - borderWidth.right, 0), + Math.max(borderRadius.getBottomRight() - borderWidth.bottom, 0), + Math.max(borderRadius.getBottomLeft() - borderWidth.left, 0), + Math.max(borderRadius.getBottomLeft() - borderWidth.bottom, 0), + }, + Path.Direction.CW); + canvas.clipPath(mPath); + hasClipPath = true; } - break; - default: - break; - } + } + + if (!hasClipPath) { + canvas.clipRect(new RectF(left, top, right, bottom)); + } + break; + default: + break; } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index e6b3594049be4b..077fec274b191a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -9,6 +9,7 @@ import android.graphics.Rect; import android.view.View; +import androidx.annotation.ColorInt; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Dynamic; @@ -20,7 +21,9 @@ import com.facebook.react.common.MapBuilder; import com.facebook.react.common.ReactConstants; import com.facebook.react.common.annotations.VisibleForTesting; +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags; import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.uimanager.BackgroundStyleApplicator; import com.facebook.react.uimanager.LengthPercentage; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.PointerEvents; @@ -32,6 +35,8 @@ import com.facebook.react.uimanager.annotations.ReactPropGroup; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.uimanager.style.BorderRadiusProp; +import com.facebook.react.uimanager.style.BorderStyle; +import com.facebook.react.uimanager.style.LogicalEdge; import java.util.Map; /** View manager for AndroidViews (plain React Views). */ @@ -129,10 +134,13 @@ public void nextFocusUp(ReactViewGroup view, int viewId) { ViewProps.BORDER_START_START_RADIUS, }) public void setBorderRadius(ReactViewGroup view, int index, Dynamic rawBorderRadius) { - @Nullable LengthPercentage borderRadius = LengthPercentage.setFromDynamic(rawBorderRadius); - - view.setBorderRadius(BorderRadiusProp.values()[index], borderRadius); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBorderRadius( + view, BorderRadiusProp.values()[index], borderRadius); + } else { + view.setBorderRadius(BorderRadiusProp.values()[index], borderRadius); + } } /** @@ -145,7 +153,14 @@ public void setBorderRadius(ReactViewGroup view, int index, float borderRadius) @ReactProp(name = "borderStyle") public void setBorderStyle(ReactViewGroup view, @Nullable String borderStyle) { - view.setBorderStyle(borderStyle); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + @Nullable + BorderStyle parsedBorderStyle = + borderStyle == null ? null : BorderStyle.fromString(borderStyle); + BackgroundStyleApplicator.setBorderStyle(view, parsedBorderStyle); + } else { + view.setBorderStyle(borderStyle); + } } @ReactProp(name = "hitSlop") @@ -220,15 +235,19 @@ public void setNeedsOffscreenAlphaCompositing( }, defaultFloat = Float.NaN) public void setBorderWidth(ReactViewGroup view, int index, float width) { - if (!Float.isNaN(width) && width < 0) { - width = Float.NaN; - } + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBorderWidth(view, LogicalEdge.values()[index], width); + } else { + if (!Float.isNaN(width) && width < 0) { + width = Float.NaN; + } - if (!Float.isNaN(width)) { - width = PixelUtil.toPixelFromDIP(width); - } + if (!Float.isNaN(width)) { + width = PixelUtil.toPixelFromDIP(width); + } - view.setBorderWidth(SPACING_TYPES[index], width); + view.setBorderWidth(SPACING_TYPES[index], width); + } } @ReactPropGroup( @@ -246,7 +265,12 @@ public void setBorderWidth(ReactViewGroup view, int index, float width) { }, customType = "Color") public void setBorderColor(ReactViewGroup view, int index, @Nullable Integer color) { - view.setBorderColor(SPACING_TYPES[index], color); + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBorderColor( + view, LogicalEdge.fromSpacingType(SPACING_TYPES[index]), color); + } else { + view.setBorderColor(SPACING_TYPES[index], color); + } } @ReactProp(name = ViewProps.COLLAPSABLE) @@ -314,6 +338,22 @@ protected void setTransformProperty( view.setBackfaceVisibilityDependantOpacity(); } + @ReactProp(name = ViewProps.BOX_SHADOW, customType = "BoxShadow") + public void setBoxShadow(ReactViewGroup view, @Nullable ReadableArray shadows) { + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBoxShadow(view, shadows); + } + } + + @Override + public void setBackgroundColor(ReactViewGroup view, @ColorInt int backgroundColor) { + if (ReactNativeFeatureFlags.enableBackgroundStyleApplicator()) { + BackgroundStyleApplicator.setBackgroundColor(view, backgroundColor); + } else { + super.setBackgroundColor(view, backgroundColor); + } + } + @Override public String getName() { return REACT_CLASS;