mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add percentages for border-radius props (#44408)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44408 Why? Previously we didn't support using percentages like: ``` style={{ width=100, height=100, borderRadius='100%', }} ``` These percentages refer to the corresponding dimension of the border box. What? - Added LengthPercentage class and LengthPercentageType enum. To track when we are dealing with percentage vs points - Now radius properties start as Dynamic which then get transformed into LengthPercentage. - Modified certain function parameters so we can consider height and width when resolving BorderRadius values With this we conditionally calculate the corresponding point (dp) value for a given percentage (considering size). Ex: ``` result = {raw_percentage_value} / 100 * (max(height, width)) ``` We know the maximum border radius for our current implementation is half the dp of the shorter side of our view, hence why we consider half our maximum view side as equivalent to 100%. Note: We still don't support vertical/horizontal border radii ## Changelog: [Android][Added] - Added support for using percentages when defining border radius related properties. Reviewed By: NickGerleman Differential Revision: D56943825 fbshipit-source-id: 3e5a9933ca90e499aff9c7d2561f5f6bb55157da
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a45c5895f9
commit
181ed33ab0
@@ -4188,6 +4188,25 @@ public class com/facebook/react/uimanager/LayoutShadowNode$$PropsSetter : com/fa
|
||||
public synthetic fun setProperty (Lcom/facebook/react/uimanager/ReactShadowNode;Ljava/lang/String;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class com/facebook/react/uimanager/LengthPercentage {
|
||||
public static final field Companion Lcom/facebook/react/uimanager/LengthPercentage$Companion;
|
||||
public fun <init> ()V
|
||||
public fun <init> (FLcom/facebook/react/uimanager/LengthPercentageType;)V
|
||||
public final fun resolve (FF)F
|
||||
public static final fun setFromDynamic (Lcom/facebook/react/bridge/Dynamic;)Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/uimanager/LengthPercentage$Companion {
|
||||
public final fun setFromDynamic (Lcom/facebook/react/bridge/Dynamic;)Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/uimanager/LengthPercentageType : java/lang/Enum {
|
||||
public static final field PERCENT Lcom/facebook/react/uimanager/LengthPercentageType;
|
||||
public static final field POINT Lcom/facebook/react/uimanager/LengthPercentageType;
|
||||
public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/uimanager/LengthPercentageType;
|
||||
public static fun values ()[Lcom/facebook/react/uimanager/LengthPercentageType;
|
||||
}
|
||||
|
||||
public class com/facebook/react/uimanager/MatrixMathHelper {
|
||||
public fun <init> ()V
|
||||
public static fun applyPerspective ([DD)V
|
||||
@@ -5483,6 +5502,7 @@ public class com/facebook/react/uimanager/drawable/CSSBackgroundDrawable : andro
|
||||
public fun getBorderColor (I)I
|
||||
public fun getBorderRadius ()Lcom/facebook/react/uimanager/style/BorderRadiusStyle;
|
||||
public fun getBorderWidthOrDefaultTo (FI)F
|
||||
public fun getComputedBorderRadius ()Lcom/facebook/react/uimanager/style/ComputedBorderRadius;
|
||||
public fun getDirectionAwareBorderInsets ()Landroid/graphics/RectF;
|
||||
public fun getFullBorderWidth ()F
|
||||
public fun getOpacity ()I
|
||||
@@ -5494,7 +5514,7 @@ public class com/facebook/react/uimanager/drawable/CSSBackgroundDrawable : andro
|
||||
public fun paddingBoxPath ()Landroid/graphics/Path;
|
||||
public fun setAlpha (I)V
|
||||
public fun setBorderColor (IFF)V
|
||||
public fun setBorderRadius (Lcom/facebook/react/uimanager/style/BorderRadiusProp;Ljava/lang/Float;)V
|
||||
public fun setBorderRadius (Lcom/facebook/react/uimanager/style/BorderRadiusProp;Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public fun setBorderRadius (Lcom/facebook/react/uimanager/style/BorderRadiusStyle;)V
|
||||
public fun setBorderStyle (Ljava/lang/String;)V
|
||||
public fun setBorderWidth (IF)V
|
||||
@@ -5819,60 +5839,61 @@ public final class com/facebook/react/uimanager/style/BorderRadiusProp : java/la
|
||||
|
||||
public final class com/facebook/react/uimanager/style/BorderRadiusStyle {
|
||||
public fun <init> ()V
|
||||
public fun <init> (Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;)V
|
||||
public synthetic fun <init> (Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public synthetic fun <init> (Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun <init> (Ljava/util/List;)V
|
||||
public final fun component1 ()Ljava/lang/Float;
|
||||
public final fun component10 ()Ljava/lang/Float;
|
||||
public final fun component11 ()Ljava/lang/Float;
|
||||
public final fun component12 ()Ljava/lang/Float;
|
||||
public final fun component13 ()Ljava/lang/Float;
|
||||
public final fun component2 ()Ljava/lang/Float;
|
||||
public final fun component3 ()Ljava/lang/Float;
|
||||
public final fun component4 ()Ljava/lang/Float;
|
||||
public final fun component5 ()Ljava/lang/Float;
|
||||
public final fun component6 ()Ljava/lang/Float;
|
||||
public final fun component7 ()Ljava/lang/Float;
|
||||
public final fun component8 ()Ljava/lang/Float;
|
||||
public final fun component9 ()Ljava/lang/Float;
|
||||
public final fun copy (Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;)Lcom/facebook/react/uimanager/style/BorderRadiusStyle;
|
||||
public static synthetic fun copy$default (Lcom/facebook/react/uimanager/style/BorderRadiusStyle;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;Ljava/lang/Float;ILjava/lang/Object;)Lcom/facebook/react/uimanager/style/BorderRadiusStyle;
|
||||
public final fun component1 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component10 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component11 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component12 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component13 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component2 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component3 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component4 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component5 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component6 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component7 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component8 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun component9 ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun copy (Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;)Lcom/facebook/react/uimanager/style/BorderRadiusStyle;
|
||||
public static synthetic fun copy$default (Lcom/facebook/react/uimanager/style/BorderRadiusStyle;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;Lcom/facebook/react/uimanager/LengthPercentage;ILjava/lang/Object;)Lcom/facebook/react/uimanager/style/BorderRadiusStyle;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun get (Lcom/facebook/react/uimanager/style/BorderRadiusProp;)Ljava/lang/Float;
|
||||
public final fun getBottomEnd ()Ljava/lang/Float;
|
||||
public final fun getBottomLeft ()Ljava/lang/Float;
|
||||
public final fun getBottomRight ()Ljava/lang/Float;
|
||||
public final fun getBottomStart ()Ljava/lang/Float;
|
||||
public final fun getEndEnd ()Ljava/lang/Float;
|
||||
public final fun getEndStart ()Ljava/lang/Float;
|
||||
public final fun getStartEnd ()Ljava/lang/Float;
|
||||
public final fun getStartStart ()Ljava/lang/Float;
|
||||
public final fun getTopEnd ()Ljava/lang/Float;
|
||||
public final fun getTopLeft ()Ljava/lang/Float;
|
||||
public final fun getTopRight ()Ljava/lang/Float;
|
||||
public final fun getTopStart ()Ljava/lang/Float;
|
||||
public final fun getUniform ()Ljava/lang/Float;
|
||||
public final fun get (Lcom/facebook/react/uimanager/style/BorderRadiusProp;)Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getBottomEnd ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getBottomLeft ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getBottomRight ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getBottomStart ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getEndEnd ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getEndStart ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getStartEnd ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getStartStart ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getTopEnd ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getTopLeft ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getTopRight ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getTopStart ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun getUniform ()Lcom/facebook/react/uimanager/LengthPercentage;
|
||||
public final fun hasRoundedBorders ()Z
|
||||
public fun hashCode ()I
|
||||
public final fun resolve (ILandroid/content/Context;)Lcom/facebook/react/uimanager/style/ComputedBorderRadius;
|
||||
public final fun set (Lcom/facebook/react/uimanager/style/BorderRadiusProp;Ljava/lang/Float;)V
|
||||
public final fun setBottomEnd (Ljava/lang/Float;)V
|
||||
public final fun setBottomLeft (Ljava/lang/Float;)V
|
||||
public final fun setBottomRight (Ljava/lang/Float;)V
|
||||
public final fun setBottomStart (Ljava/lang/Float;)V
|
||||
public final fun setEndEnd (Ljava/lang/Float;)V
|
||||
public final fun setEndStart (Ljava/lang/Float;)V
|
||||
public final fun setStartEnd (Ljava/lang/Float;)V
|
||||
public final fun setStartStart (Ljava/lang/Float;)V
|
||||
public final fun setTopEnd (Ljava/lang/Float;)V
|
||||
public final fun setTopLeft (Ljava/lang/Float;)V
|
||||
public final fun setTopRight (Ljava/lang/Float;)V
|
||||
public final fun setTopStart (Ljava/lang/Float;)V
|
||||
public final fun setUniform (Ljava/lang/Float;)V
|
||||
public final fun resolve (ILandroid/content/Context;FF)Lcom/facebook/react/uimanager/style/ComputedBorderRadius;
|
||||
public final fun set (Lcom/facebook/react/uimanager/style/BorderRadiusProp;Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setBottomEnd (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setBottomLeft (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setBottomRight (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setBottomStart (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setEndEnd (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setEndStart (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setStartEnd (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setStartStart (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setTopEnd (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setTopLeft (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setTopRight (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setTopStart (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public final fun setUniform (Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/uimanager/style/ComputedBorderRadius {
|
||||
public fun <init> ()V
|
||||
public fun <init> (FFFF)V
|
||||
public final fun component1 ()F
|
||||
public final fun component2 ()F
|
||||
@@ -7904,7 +7925,7 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro
|
||||
public fun setBorderColor (IFF)V
|
||||
public fun setBorderRadius (F)V
|
||||
public fun setBorderRadius (FI)V
|
||||
public fun setBorderRadius (Lcom/facebook/react/uimanager/style/BorderRadiusProp;Ljava/lang/Float;)V
|
||||
public fun setBorderRadius (Lcom/facebook/react/uimanager/style/BorderRadiusProp;Lcom/facebook/react/uimanager/LengthPercentage;)V
|
||||
public fun setBorderStyle (Ljava/lang/String;)V
|
||||
public fun setBorderWidth (IF)V
|
||||
public fun setHitSlopRect (Landroid/graphics/Rect;)V
|
||||
@@ -7940,6 +7961,7 @@ public class com/facebook/react/views/view/ReactViewManager : com/facebook/react
|
||||
public fun setBackfaceVisibility (Lcom/facebook/react/views/view/ReactViewGroup;Ljava/lang/String;)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 setCollapsable (Lcom/facebook/react/views/view/ReactViewGroup;Z)V
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.uimanager
|
||||
|
||||
import com.facebook.common.logging.FLog
|
||||
import com.facebook.react.bridge.Dynamic
|
||||
import com.facebook.react.bridge.ReadableType
|
||||
import com.facebook.react.common.ReactConstants
|
||||
import java.lang.NumberFormatException
|
||||
|
||||
public enum class LengthPercentageType {
|
||||
POINT,
|
||||
PERCENT,
|
||||
}
|
||||
|
||||
public class LengthPercentage(
|
||||
private val value: Float,
|
||||
private val unit: LengthPercentageType,
|
||||
) {
|
||||
public companion object {
|
||||
@JvmStatic
|
||||
public fun setFromDynamic(dynamic: Dynamic): LengthPercentage? {
|
||||
return when (dynamic.getType()) {
|
||||
ReadableType.Number -> {
|
||||
val value = dynamic.asDouble()
|
||||
if (value > 0f) {
|
||||
LengthPercentage(PixelUtil.toPixelFromDIP(value), LengthPercentageType.POINT)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
ReadableType.String -> {
|
||||
val s = dynamic.asString()
|
||||
if (s.endsWith("%")) {
|
||||
try {
|
||||
val value = s.substring(0, s.length - 1).toFloat()
|
||||
if (value > 0f) {
|
||||
LengthPercentage(value, LengthPercentageType.PERCENT)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
FLog.w(ReactConstants.TAG, "Invalid percentage format: $s")
|
||||
null
|
||||
}
|
||||
} else {
|
||||
FLog.w(ReactConstants.TAG, "Invalid string value: $s")
|
||||
null
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
FLog.w(ReactConstants.TAG, "Unsupported type for radius property: ${dynamic.getType()}")
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun resolve(width: Float, height: Float): Float {
|
||||
if (unit == LengthPercentageType.PERCENT) {
|
||||
return (value / 100) * Math.max(width, height)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
public constructor() : this(0f, LengthPercentageType.POINT)
|
||||
}
|
||||
+37
-11
@@ -27,11 +27,14 @@ import androidx.core.graphics.ColorUtils;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||
import com.facebook.react.uimanager.FloatUtil;
|
||||
import com.facebook.react.uimanager.LengthPercentage;
|
||||
import com.facebook.react.uimanager.LengthPercentageType;
|
||||
import com.facebook.react.uimanager.Spacing;
|
||||
import com.facebook.react.uimanager.style.BorderRadiusProp;
|
||||
import com.facebook.react.uimanager.style.BorderRadiusStyle;
|
||||
import com.facebook.react.uimanager.style.ComputedBorderRadius;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A subclass of {@link Drawable} used for background of {@link
|
||||
@@ -114,6 +117,7 @@ public class CSSBackgroundDrawable extends Drawable {
|
||||
private final float mGapBetweenPaths = 0.8f;
|
||||
|
||||
private BorderRadiusStyle mBorderRadius = new BorderRadiusStyle();
|
||||
private ComputedBorderRadius mComputedBorderRadius = new ComputedBorderRadius();
|
||||
private final Context mContext;
|
||||
private int mLayoutDirection;
|
||||
|
||||
@@ -235,23 +239,36 @@ public class CSSBackgroundDrawable extends Drawable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setBorderRadius(BorderRadiusProp, Float)} instead.
|
||||
* @deprecated Use {@link #setBorderRadius(BorderRadiusProp, LengthPercentage)} instead.
|
||||
*/
|
||||
public void setRadius(float radius) {
|
||||
@Nullable Float boxedRadius = Float.isNaN(radius) ? null : Float.valueOf(radius);
|
||||
setBorderRadius(BorderRadiusProp.BORDER_RADIUS, boxedRadius);
|
||||
if (boxedRadius == null) {
|
||||
setBorderRadius(BorderRadiusProp.BORDER_RADIUS, null);
|
||||
} else {
|
||||
setBorderRadius(
|
||||
BorderRadiusProp.BORDER_RADIUS,
|
||||
new LengthPercentage(boxedRadius, LengthPercentageType.POINT));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setBorderRadius(BorderRadiusProp, Float)} instead.
|
||||
* @deprecated Use {@link #setBorderRadius(BorderRadiusProp, LengthPercentage)} instead.
|
||||
*/
|
||||
public void setRadius(float radius, int position) {
|
||||
@Nullable Float boxedRadius = Float.isNaN(radius) ? null : Float.valueOf(radius);
|
||||
setBorderRadius(BorderRadiusProp.values()[position], boxedRadius);
|
||||
|
||||
if (boxedRadius == null) {
|
||||
mBorderRadius.set(BorderRadiusProp.values()[position], null);
|
||||
} else {
|
||||
setBorderRadius(
|
||||
BorderRadiusProp.values()[position],
|
||||
new LengthPercentage(boxedRadius, LengthPercentageType.POINT));
|
||||
}
|
||||
}
|
||||
|
||||
public void setBorderRadius(BorderRadiusProp property, @Nullable Float radius) {
|
||||
if (!FloatUtil.floatsEqual(mBorderRadius.getUniform(), radius)) {
|
||||
public void setBorderRadius(BorderRadiusProp property, @Nullable LengthPercentage radius) {
|
||||
if (!Objects.equals(radius, mBorderRadius.get(property))) {
|
||||
mBorderRadius.set(property, radius);
|
||||
mNeedUpdatePathForBorderRadius = true;
|
||||
invalidateSelf();
|
||||
@@ -266,6 +283,10 @@ public class CSSBackgroundDrawable extends Drawable {
|
||||
return mBorderRadius;
|
||||
}
|
||||
|
||||
public ComputedBorderRadius getComputedBorderRadius() {
|
||||
return mComputedBorderRadius;
|
||||
}
|
||||
|
||||
public void setColor(int color) {
|
||||
mColor = color;
|
||||
invalidateSelf();
|
||||
@@ -568,11 +589,16 @@ public class CSSBackgroundDrawable extends Drawable {
|
||||
mTempRectForCenterDrawPath.left += borderWidth.left * 0.5f;
|
||||
mTempRectForCenterDrawPath.right -= borderWidth.right * 0.5f;
|
||||
|
||||
ComputedBorderRadius radius = mBorderRadius.resolve(mLayoutDirection, mContext);
|
||||
float topLeftRadius = radius.getTopLeft();
|
||||
float topRightRadius = radius.getTopRight();
|
||||
float bottomLeftRadius = radius.getBottomLeft();
|
||||
float bottomRightRadius = radius.getBottomRight();
|
||||
mComputedBorderRadius =
|
||||
mBorderRadius.resolve(
|
||||
mLayoutDirection,
|
||||
mContext,
|
||||
mOuterClipTempRectForBorderRadius.width(),
|
||||
mOuterClipTempRectForBorderRadius.height());
|
||||
float topLeftRadius = mComputedBorderRadius.getTopLeft();
|
||||
float topRightRadius = mComputedBorderRadius.getTopRight();
|
||||
float bottomLeftRadius = mComputedBorderRadius.getBottomLeft();
|
||||
float bottomRightRadius = mComputedBorderRadius.getBottomRight();
|
||||
|
||||
final float innerTopLeftRadiusX = Math.max(topLeftRadius - borderWidth.left, 0);
|
||||
final float innerTopLeftRadiusY = Math.max(topLeftRadius - borderWidth.top, 0);
|
||||
|
||||
+53
-42
@@ -10,9 +10,11 @@ package com.facebook.react.uimanager.style
|
||||
import android.content.Context
|
||||
import android.util.LayoutDirection
|
||||
import com.facebook.react.modules.i18nmanager.I18nUtil
|
||||
import com.facebook.react.uimanager.LengthPercentage
|
||||
|
||||
/** Represents the collection of possible border radius style properties. */
|
||||
public enum class BorderRadiusProp {
|
||||
BORDER_RADIUS,
|
||||
BORDER_TOP_LEFT_RADIUS,
|
||||
BORDER_TOP_RIGHT_RADIUS,
|
||||
BORDER_BOTTOM_RIGHT_RADIUS,
|
||||
@@ -25,30 +27,29 @@ public enum class BorderRadiusProp {
|
||||
BORDER_END_START_RADIUS,
|
||||
BORDER_START_END_RADIUS,
|
||||
BORDER_START_START_RADIUS,
|
||||
BORDER_RADIUS,
|
||||
}
|
||||
|
||||
/** Represents all logical properties and shorthands for border radius. */
|
||||
public data class BorderRadiusStyle(
|
||||
var uniform: Float? = null,
|
||||
var topLeft: Float? = null,
|
||||
var topRight: Float? = null,
|
||||
var bottomLeft: Float? = null,
|
||||
var bottomRight: Float? = null,
|
||||
var topStart: Float? = null,
|
||||
var topEnd: Float? = null,
|
||||
var bottomStart: Float? = null,
|
||||
var bottomEnd: Float? = null,
|
||||
var startStart: Float? = null,
|
||||
var startEnd: Float? = null,
|
||||
var endStart: Float? = null,
|
||||
var endEnd: Float? = null
|
||||
var uniform: LengthPercentage? = null,
|
||||
var topLeft: LengthPercentage? = null,
|
||||
var topRight: LengthPercentage? = null,
|
||||
var bottomLeft: LengthPercentage? = null,
|
||||
var bottomRight: LengthPercentage? = null,
|
||||
var topStart: LengthPercentage? = null,
|
||||
var topEnd: LengthPercentage? = null,
|
||||
var bottomStart: LengthPercentage? = null,
|
||||
var bottomEnd: LengthPercentage? = null,
|
||||
var startStart: LengthPercentage? = null,
|
||||
var startEnd: LengthPercentage? = null,
|
||||
var endStart: LengthPercentage? = null,
|
||||
var endEnd: LengthPercentage? = null
|
||||
) {
|
||||
public constructor(properties: List<Pair<BorderRadiusProp, Float>>) : this() {
|
||||
public constructor(properties: List<Pair<BorderRadiusProp, LengthPercentage>>) : this() {
|
||||
properties.forEach { (k, v) -> set(k, v) }
|
||||
}
|
||||
|
||||
public fun set(property: BorderRadiusProp, value: Float?) {
|
||||
public fun set(property: BorderRadiusProp, value: LengthPercentage?) {
|
||||
when (property) {
|
||||
BorderRadiusProp.BORDER_RADIUS -> uniform = value
|
||||
BorderRadiusProp.BORDER_TOP_LEFT_RADIUS -> topLeft = value
|
||||
@@ -66,7 +67,7 @@ public data class BorderRadiusStyle(
|
||||
}
|
||||
}
|
||||
|
||||
public fun get(property: BorderRadiusProp): Float? {
|
||||
public fun get(property: BorderRadiusProp): LengthPercentage? {
|
||||
return when (property) {
|
||||
BorderRadiusProp.BORDER_RADIUS -> uniform
|
||||
BorderRadiusProp.BORDER_TOP_LEFT_RADIUS -> topLeft
|
||||
@@ -85,45 +86,55 @@ public data class BorderRadiusStyle(
|
||||
}
|
||||
|
||||
public fun hasRoundedBorders(): Boolean {
|
||||
return ((uniform ?: 0f) > 0f) ||
|
||||
((topLeft ?: 0f) > 0f) ||
|
||||
((topRight ?: 0f) > 0f) ||
|
||||
((bottomLeft ?: 0f) > 0f) ||
|
||||
((bottomRight ?: 0f) > 0f) ||
|
||||
((topStart ?: 0f) > 0f) ||
|
||||
((topEnd ?: 0f) > 0f) ||
|
||||
((bottomStart ?: 0f) > 0f) ||
|
||||
((bottomEnd ?: 0f) > 0f) ||
|
||||
((startStart ?: 0f) > 0f) ||
|
||||
((startEnd ?: 0f) > 0f) ||
|
||||
((endStart ?: 0f) > 0f) ||
|
||||
((endEnd ?: 0f) > 0f)
|
||||
return uniform != null ||
|
||||
topLeft != null ||
|
||||
topRight != null ||
|
||||
bottomLeft != null ||
|
||||
bottomRight != null ||
|
||||
topStart != null ||
|
||||
topEnd != null ||
|
||||
bottomStart != null ||
|
||||
bottomEnd != null ||
|
||||
startStart != null ||
|
||||
startEnd != null ||
|
||||
endStart != null ||
|
||||
endEnd != null
|
||||
}
|
||||
|
||||
public fun resolve(
|
||||
layoutDirection: Int,
|
||||
context: Context,
|
||||
width: Float,
|
||||
height: Float,
|
||||
): ComputedBorderRadius {
|
||||
val topLeft: LengthPercentage? = startStart ?: topStart ?: topLeft ?: uniform
|
||||
val topRight: LengthPercentage? = endStart ?: topEnd ?: topRight ?: uniform
|
||||
val bottomLeft: LengthPercentage? = startEnd ?: bottomStart ?: bottomLeft ?: uniform
|
||||
val bottomRight: LengthPercentage? = endEnd ?: bottomEnd ?: bottomRight ?: uniform
|
||||
|
||||
return when (layoutDirection) {
|
||||
LayoutDirection.LTR ->
|
||||
ComputedBorderRadius(
|
||||
topLeft = startStart ?: topStart ?: topLeft ?: uniform ?: 0f,
|
||||
topRight = endStart ?: topEnd ?: topRight ?: uniform ?: 0f,
|
||||
bottomLeft = startEnd ?: bottomStart ?: bottomLeft ?: uniform ?: 0f,
|
||||
bottomRight = endEnd ?: bottomEnd ?: bottomRight ?: uniform ?: 0f)
|
||||
topLeft = topLeft?.resolve(width, height) ?: 0f,
|
||||
topRight = topRight?.resolve(width, height) ?: 0f,
|
||||
bottomLeft = bottomLeft?.resolve(width, height) ?: 0f,
|
||||
bottomRight = bottomRight?.resolve(width, height) ?: 0f,
|
||||
)
|
||||
LayoutDirection.RTL ->
|
||||
if (I18nUtil.getInstance().doLeftAndRightSwapInRTL(context)) {
|
||||
ComputedBorderRadius(
|
||||
topLeft = endStart ?: topEnd ?: topRight ?: uniform ?: 0f,
|
||||
topRight = startStart ?: topStart ?: topLeft ?: uniform ?: 0f,
|
||||
bottomLeft = endEnd ?: bottomStart ?: bottomRight ?: uniform ?: 0f,
|
||||
bottomRight = startEnd ?: bottomEnd ?: bottomLeft ?: uniform ?: 0f)
|
||||
topLeft = topRight?.resolve(width, height) ?: 0f,
|
||||
topRight = topLeft?.resolve(width, height) ?: 0f,
|
||||
bottomLeft = bottomRight?.resolve(width, height) ?: 0f,
|
||||
bottomRight = bottomLeft?.resolve(width, height) ?: 0f,
|
||||
)
|
||||
} else {
|
||||
ComputedBorderRadius(
|
||||
topLeft = endStart ?: topEnd ?: topLeft ?: uniform ?: 0f,
|
||||
topRight = startStart ?: topStart ?: topRight ?: uniform ?: 0f,
|
||||
bottomLeft = endEnd ?: bottomStart ?: bottomLeft ?: uniform ?: 0f,
|
||||
bottomRight = startEnd ?: bottomEnd ?: bottomRight ?: uniform ?: 0f)
|
||||
topLeft = topRight?.resolve(width, height) ?: 0f,
|
||||
topRight = topLeft?.resolve(width, height) ?: 0f,
|
||||
bottomLeft = bottomRight?.resolve(width, height) ?: 0f,
|
||||
bottomRight = bottomLeft?.resolve(width, height) ?: 0f,
|
||||
)
|
||||
}
|
||||
else -> throw IllegalArgumentException("Expected resolved layout direction")
|
||||
}
|
||||
|
||||
+2
@@ -17,4 +17,6 @@ public data class ComputedBorderRadius(
|
||||
public fun hasRoundedBorders(): Boolean {
|
||||
return topLeft > 0f || topRight > 0f || bottomLeft > 0f || bottomRight > 0f
|
||||
}
|
||||
|
||||
public constructor() : this(0f, 0f, 0f, 0f)
|
||||
}
|
||||
|
||||
+20
-19
@@ -37,6 +37,7 @@ import com.facebook.react.touch.OnInterceptTouchEventListener;
|
||||
import com.facebook.react.touch.ReactHitSlopView;
|
||||
import com.facebook.react.touch.ReactInterceptingViewGroup;
|
||||
import com.facebook.react.uimanager.IllegalViewOperationException;
|
||||
import com.facebook.react.uimanager.LengthPercentage;
|
||||
import com.facebook.react.uimanager.MeasureSpecAssertions;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.uimanager.ReactClippingProhibitedView;
|
||||
@@ -123,7 +124,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
private @Nullable String mOverflow;
|
||||
private PointerEvents mPointerEvents;
|
||||
private @Nullable ChildrenLayoutChangeListener mChildrenLayoutChangeListener;
|
||||
private @Nullable ReactViewBackgroundDrawable mReactBackgroundDrawable;
|
||||
private @Nullable CSSBackgroundDrawable mCSSBackgroundDrawable;
|
||||
private @Nullable OnInterceptTouchEventListener mOnInterceptTouchEventListener;
|
||||
private boolean mNeedsOffscreenAlphaCompositing;
|
||||
private @Nullable ViewGroupDrawingOrderHelper mDrawingOrderHelper;
|
||||
@@ -153,7 +154,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
mOverflow = null;
|
||||
mPointerEvents = PointerEvents.AUTO;
|
||||
mChildrenLayoutChangeListener = null;
|
||||
mReactBackgroundDrawable = null;
|
||||
mCSSBackgroundDrawable = null;
|
||||
mOnInterceptTouchEventListener = null;
|
||||
mNeedsOffscreenAlphaCompositing = false;
|
||||
mDrawingOrderHelper = null;
|
||||
@@ -200,8 +201,8 @@ public class ReactViewGroup extends ViewGroup
|
||||
|
||||
@Override
|
||||
public void onRtlPropertiesChanged(int layoutDirection) {
|
||||
if (mReactBackgroundDrawable != null) {
|
||||
mReactBackgroundDrawable.setResolvedLayoutDirection(mLayoutDirection);
|
||||
if (mCSSBackgroundDrawable != null) {
|
||||
mCSSBackgroundDrawable.setResolvedLayoutDirection(mLayoutDirection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +225,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
|
||||
@Override
|
||||
public void setBackgroundColor(int color) {
|
||||
if (color == Color.TRANSPARENT && mReactBackgroundDrawable == null) {
|
||||
if (color == Color.TRANSPARENT && mCSSBackgroundDrawable == null) {
|
||||
// don't do anything, no need to allocate ReactBackgroundDrawable for transparent background
|
||||
} else {
|
||||
getOrCreateReactViewBackground().setColor(color);
|
||||
@@ -243,9 +244,9 @@ public class ReactViewGroup extends ViewGroup
|
||||
// as a background previously. This will not work correctly as the drawable callback logic is
|
||||
// messed up in AOSP
|
||||
updateBackgroundDrawable(null);
|
||||
if (mReactBackgroundDrawable != null && background != null) {
|
||||
if (mCSSBackgroundDrawable != null && background != null) {
|
||||
LayerDrawable layerDrawable =
|
||||
new LayerDrawable(new Drawable[] {mReactBackgroundDrawable, background});
|
||||
new LayerDrawable(new Drawable[] {mCSSBackgroundDrawable, background});
|
||||
updateBackgroundDrawable(layerDrawable);
|
||||
} else if (background != null) {
|
||||
updateBackgroundDrawable(background);
|
||||
@@ -332,7 +333,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
backgroundDrawable.setRadius(borderRadius, position);
|
||||
}
|
||||
|
||||
public void setBorderRadius(BorderRadiusProp property, @Nullable Float borderRadius) {
|
||||
public void setBorderRadius(BorderRadiusProp property, @Nullable LengthPercentage borderRadius) {
|
||||
CSSBackgroundDrawable backgroundDrawable = getOrCreateReactViewBackground();
|
||||
backgroundDrawable.setBorderRadius(property, borderRadius);
|
||||
}
|
||||
@@ -791,26 +792,26 @@ public class ReactViewGroup extends ViewGroup
|
||||
return DEFAULT_BACKGROUND_COLOR;
|
||||
}
|
||||
|
||||
/* package */ ReactViewBackgroundDrawable getOrCreateReactViewBackground() {
|
||||
if (mReactBackgroundDrawable == null) {
|
||||
mReactBackgroundDrawable = new ReactViewBackgroundDrawable(getContext());
|
||||
/* package */ CSSBackgroundDrawable getOrCreateReactViewBackground() {
|
||||
if (mCSSBackgroundDrawable == null) {
|
||||
mCSSBackgroundDrawable = new CSSBackgroundDrawable(getContext());
|
||||
Drawable backgroundDrawable = getBackground();
|
||||
updateBackgroundDrawable(
|
||||
null); // required so that drawable callback is cleared before we add the
|
||||
// drawable back as a part of LayerDrawable
|
||||
if (backgroundDrawable == null) {
|
||||
updateBackgroundDrawable(mReactBackgroundDrawable);
|
||||
updateBackgroundDrawable(mCSSBackgroundDrawable);
|
||||
} else {
|
||||
LayerDrawable layerDrawable =
|
||||
new LayerDrawable(new Drawable[] {mReactBackgroundDrawable, backgroundDrawable});
|
||||
new LayerDrawable(new Drawable[] {mCSSBackgroundDrawable, backgroundDrawable});
|
||||
updateBackgroundDrawable(layerDrawable);
|
||||
}
|
||||
|
||||
mLayoutDirection =
|
||||
I18nUtil.getInstance().isRTL(getContext()) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
|
||||
mReactBackgroundDrawable.setResolvedLayoutDirection(mLayoutDirection);
|
||||
mCSSBackgroundDrawable.setResolvedLayoutDirection(mLayoutDirection);
|
||||
}
|
||||
return mReactBackgroundDrawable;
|
||||
return mCSSBackgroundDrawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -849,7 +850,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
* @param drawable {@link Drawable} The Drawable to use as the background, or null to remove the
|
||||
* background
|
||||
*/
|
||||
/* package */ void updateBackgroundDrawable(Drawable drawable) {
|
||||
/* package */ void updateBackgroundDrawable(@Nullable Drawable drawable) {
|
||||
super.setBackground(drawable);
|
||||
}
|
||||
|
||||
@@ -909,8 +910,8 @@ public class ReactViewGroup extends ViewGroup
|
||||
|
||||
boolean hasClipPath = false;
|
||||
|
||||
if (mReactBackgroundDrawable != null) {
|
||||
final RectF borderWidth = mReactBackgroundDrawable.getDirectionAwareBorderInsets();
|
||||
if (mCSSBackgroundDrawable != null) {
|
||||
final RectF borderWidth = mCSSBackgroundDrawable.getDirectionAwareBorderInsets();
|
||||
|
||||
if (borderWidth.top > 0
|
||||
|| borderWidth.left > 0
|
||||
@@ -923,7 +924,7 @@ public class ReactViewGroup extends ViewGroup
|
||||
}
|
||||
|
||||
final ComputedBorderRadius borderRadius =
|
||||
mReactBackgroundDrawable.getBorderRadius().resolve(mLayoutDirection, getContext());
|
||||
mCSSBackgroundDrawable.getComputedBorderRadius();
|
||||
|
||||
if (borderRadius.hasRoundedBorders()) {
|
||||
if (mPath == null) {
|
||||
|
||||
+15
-15
@@ -13,6 +13,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.bridge.DynamicFromObject;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
@@ -21,6 +22,7 @@ import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.LengthPercentage;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.uimanager.Spacing;
|
||||
@@ -30,6 +32,7 @@ import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.uimanager.annotations.ReactPropGroup;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.style.BorderRadiusProp;
|
||||
import com.facebook.yoga.YogaConstants;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -126,22 +129,19 @@ public class ReactViewManager extends ReactClippingViewManager<ReactViewGroup> {
|
||||
ViewProps.BORDER_END_START_RADIUS,
|
||||
ViewProps.BORDER_START_END_RADIUS,
|
||||
ViewProps.BORDER_START_START_RADIUS,
|
||||
},
|
||||
defaultFloat = YogaConstants.UNDEFINED)
|
||||
})
|
||||
public void setBorderRadius(ReactViewGroup view, int index, Dynamic rawBorderRadius) {
|
||||
|
||||
@Nullable LengthPercentage borderRadius = LengthPercentage.setFromDynamic(rawBorderRadius);
|
||||
|
||||
view.setBorderRadius(BorderRadiusProp.values()[index], borderRadius);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setBorderRadius(ReactViewGroup, int, Dynamic)} instead.
|
||||
*/
|
||||
public void setBorderRadius(ReactViewGroup view, int index, float borderRadius) {
|
||||
if (!YogaConstants.isUndefined(borderRadius) && borderRadius < 0) {
|
||||
borderRadius = YogaConstants.UNDEFINED;
|
||||
}
|
||||
|
||||
if (!YogaConstants.isUndefined(borderRadius)) {
|
||||
borderRadius = PixelUtil.toPixelFromDIP(borderRadius);
|
||||
}
|
||||
|
||||
if (index == 0) {
|
||||
view.setBorderRadius(borderRadius);
|
||||
} else {
|
||||
view.setBorderRadius(borderRadius, index - 1);
|
||||
}
|
||||
setBorderRadius(view, index, new DynamicFromObject(borderRadius));
|
||||
}
|
||||
|
||||
@ReactProp(name = "borderStyle")
|
||||
|
||||
Reference in New Issue
Block a user