Skip to content

Commit 41e0e43

Browse files
fix: borderRadius outline and border drawable fixes
Android: - Fall back to ViewOutlineProvider.BACKGROUND when borderRadius is not animated, so elevation shadows respect style borderRadius. - Sync animated borderRadius to BorderDrawable via BackgroundStyleApplicator.setBorderRadius so borders follow animated corner radius. iOS: - Stop setting masksToBounds for animated borderRadius. cornerRadius alone rounds the background visually; masksToBounds clips children and shadows unnecessarily (RN defaults to overflow:visible).
1 parent 7916950 commit 41e0e43

2 files changed

Lines changed: 437 additions & 421 deletions

File tree

android/src/main/java/com/ease/EaseView.kt

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import androidx.dynamicanimation.animation.SpringAnimation
1515
import androidx.dynamicanimation.animation.SpringForce
1616
import com.facebook.react.bridge.ReadableMap
1717
import com.facebook.react.uimanager.BackgroundStyleApplicator
18+
import com.facebook.react.uimanager.LengthPercentage
19+
import com.facebook.react.uimanager.LengthPercentageType
20+
import com.facebook.react.uimanager.PixelUtil
21+
import com.facebook.react.uimanager.style.BorderRadiusProp
1822
import com.facebook.react.uimanager.style.LogicalEdge
1923
import com.facebook.react.views.view.ReactViewGroup
2024
import kotlin.math.sqrt
@@ -160,6 +164,12 @@ class EaseView(context: Context) : ReactViewGroup(context) {
160164
clipToOutline = false
161165
}
162166
invalidateOutline()
167+
// Sync border drawable so borders follow the animated corner radius.
168+
// Value is in pixels; convert back to DIPs for BackgroundStyleApplicator.
169+
val dip = PixelUtil.toDIPFromPixel(value)
170+
BackgroundStyleApplicator.setBorderRadius(
171+
this, BorderRadiusProp.BORDER_RADIUS,
172+
LengthPercentage(dip, LengthPercentageType.POINT))
163173
}
164174
}
165175

@@ -246,15 +256,16 @@ class EaseView(context: Context) : ReactViewGroup(context) {
246256
cameraDistance = density * density * perspective * CAMERA_DISTANCE_NORMALIZATION_MULTIPLIER
247257
}
248258

259+
// Custom outline provider used when borderRadius is animated.
260+
// Reads _borderRadius dynamically — invalidated on each frame by setAnimateBorderRadius.
261+
private val animatedOutlineProvider = object : ViewOutlineProvider() {
262+
override fun getOutline(view: View, outline: Outline) {
263+
outline.setRoundRect(0, 0, view.width, view.height, _borderRadius)
264+
}
265+
}
266+
249267
init {
250268
applyCameraDistance(1280f)
251-
252-
// ViewOutlineProvider reads _borderRadius dynamically — set once, invalidated on each frame.
253-
outlineProvider = object : ViewOutlineProvider() {
254-
override fun getOutline(view: View, outline: Outline) {
255-
outline.setRoundRect(0, 0, view.width, view.height, _borderRadius)
256-
}
257-
}
258269
}
259270

260271
// --- Hardware layer management ---
@@ -320,6 +331,16 @@ class EaseView(context: Context) : ReactViewGroup(context) {
320331
// Bitmask: which properties are animated. Non-animated = let style handle.
321332
val mask = animatedProperties
322333

334+
// Use custom outline provider only when borderRadius is animated.
335+
// Otherwise fall back to BACKGROUND provider so elevation shadows
336+
// respect the style borderRadius from the background drawable.
337+
val needsCustomOutline = mask and MASK_BORDER_RADIUS != 0
338+
if (needsCustomOutline && outlineProvider !== animatedOutlineProvider) {
339+
outlineProvider = animatedOutlineProvider
340+
} else if (!needsCustomOutline && outlineProvider === animatedOutlineProvider) {
341+
outlineProvider = ViewOutlineProvider.BACKGROUND
342+
}
343+
323344
if (isFirstMount) {
324345
isFirstMount = false
325346

@@ -974,6 +995,7 @@ class EaseView(context: Context) : ReactViewGroup(context) {
974995
applyBackgroundColor(Color.TRANSPARENT)
975996
setAnimateBorderWidth(0f)
976997
applyBorderColor(Color.BLACK)
998+
outlineProvider = ViewOutlineProvider.BACKGROUND
977999

9781000
transformPerspective = 1280f
9791001
isFirstMount = true

0 commit comments

Comments
 (0)