react-native-morph-card 0.1.11 → 0.1.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -100,11 +100,35 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
100
100
|
|
|
101
101
|
// ── Snapshot ──
|
|
102
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Capture a snapshot of the source card's children WITHOUT border radius clipping.
|
|
105
|
+
* Like iOS, we want the raw content (e.g. the full rectangular image), not what's
|
|
106
|
+
* visually clipped on screen. The border radius is applied separately during animation.
|
|
107
|
+
*/
|
|
103
108
|
private fun captureSnapshot(): Bitmap {
|
|
104
109
|
val w = width
|
|
105
110
|
val h = height
|
|
106
111
|
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
|
|
107
112
|
val canvas = Canvas(bitmap)
|
|
113
|
+
|
|
114
|
+
// Temporarily disable clipToOutline on all descendant views so that
|
|
115
|
+
// the snapshot captures the full rectangular content, not the clipped version.
|
|
116
|
+
val clippedViews = mutableListOf<View>()
|
|
117
|
+
fun disableClipping(view: View) {
|
|
118
|
+
if (view.clipToOutline) {
|
|
119
|
+
clippedViews.add(view)
|
|
120
|
+
view.clipToOutline = false
|
|
121
|
+
}
|
|
122
|
+
if (view is ViewGroup) {
|
|
123
|
+
for (i in 0 until view.childCount) {
|
|
124
|
+
disableClipping(view.getChildAt(i))
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
for (i in 0 until childCount) {
|
|
129
|
+
disableClipping(getChildAt(i))
|
|
130
|
+
}
|
|
131
|
+
|
|
108
132
|
for (i in 0 until childCount) {
|
|
109
133
|
val child = getChildAt(i)
|
|
110
134
|
if (child.visibility != VISIBLE) continue
|
|
@@ -113,6 +137,12 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
113
137
|
child.draw(canvas)
|
|
114
138
|
canvas.restore()
|
|
115
139
|
}
|
|
140
|
+
|
|
141
|
+
// Restore clipToOutline on all views that had it
|
|
142
|
+
for (view in clippedViews) {
|
|
143
|
+
view.clipToOutline = true
|
|
144
|
+
}
|
|
145
|
+
|
|
116
146
|
return bitmap
|
|
117
147
|
}
|
|
118
148
|
|
|
@@ -502,8 +532,8 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
502
532
|
removeHierarchyListener()
|
|
503
533
|
|
|
504
534
|
// The PixelCopy blocker bitmap contains the source card at its original position.
|
|
505
|
-
//
|
|
506
|
-
//
|
|
535
|
+
// Replace the card area with the surrounding background color so the card wrapper
|
|
536
|
+
// animates without a duplicate underneath, and no transparent hole is visible.
|
|
507
537
|
val blockerImg = wrapper.findViewWithTag<FrameLayout>("morphCardWrapper")?.let { cardW ->
|
|
508
538
|
(0 until wrapper.childCount).map { wrapper.getChildAt(it) }.firstOrNull { it !== cardW }
|
|
509
539
|
} as? ImageView
|
|
@@ -511,13 +541,22 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
511
541
|
val bmp = (blockerImg.drawable as? BitmapDrawable)?.bitmap
|
|
512
542
|
if (bmp != null) {
|
|
513
543
|
val clearCanvas = Canvas(bmp)
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
544
|
+
// Sample the background color from a pixel just outside the card area
|
|
545
|
+
val sampleX = max(0, cardLeft.toInt() - 1)
|
|
546
|
+
val sampleY = min(bmp.height - 1, (cardTop + cardHeight / 2).toInt())
|
|
547
|
+
val bgColor = if (sampleX >= 0 && sampleX < bmp.width && sampleY >= 0 && sampleY < bmp.height) {
|
|
548
|
+
bmp.getPixel(sampleX, sampleY)
|
|
518
549
|
} else {
|
|
519
|
-
|
|
550
|
+
Color.WHITE
|
|
520
551
|
}
|
|
552
|
+
// First clear the card area to transparent
|
|
553
|
+
val clearPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
554
|
+
clearPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
|
|
555
|
+
clearCanvas.drawRect(cardLeft, cardTop, cardLeft + cardWidth, cardTop + cardHeight, clearPaint)
|
|
556
|
+
// Then fill with the sampled background color (no transparent hole)
|
|
557
|
+
val fillPaint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
558
|
+
fillPaint.color = bgColor
|
|
559
|
+
clearCanvas.drawRect(cardLeft, cardTop, cardLeft + cardWidth, cardTop + cardHeight, fillPaint)
|
|
521
560
|
blockerImg.invalidate()
|
|
522
561
|
}
|
|
523
562
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-morph-card",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "Native card-to-modal morph transition for React Native. iOS App Store-style expand animation.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|