react-native-morph-card 0.1.15 → 0.2.1
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,124 +100,19 @@ 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
|
-
*
|
|
108
|
-
* This disables both Android's clipToOutline AND Fresco's RoundingParams (used by
|
|
109
|
-
* React Native's Image component) to capture the full rectangular content.
|
|
110
|
-
*/
|
|
111
103
|
private fun captureSnapshot(): Bitmap {
|
|
112
104
|
val w = width
|
|
113
105
|
val h = height
|
|
114
106
|
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
|
|
115
107
|
val canvas = Canvas(bitmap)
|
|
116
|
-
|
|
117
|
-
// Track Fresco views to restore rounding after capture
|
|
118
|
-
data class FrescoState(val view: View, val hierarchy: Any, val roundingParams: Any)
|
|
119
|
-
val frescoStates = mutableListOf<FrescoState>()
|
|
120
|
-
// Track views whose clipToOutline was disabled
|
|
121
|
-
val clippedViews = mutableListOf<View>()
|
|
122
|
-
|
|
123
|
-
// Map of Fresco views to their hierarchy (for drawing drawable directly)
|
|
124
|
-
val frescoViews = mutableMapOf<View, Any>()
|
|
125
|
-
|
|
126
|
-
fun prepareView(view: View) {
|
|
127
|
-
// Disable outline clipping
|
|
128
|
-
if (view.clipToOutline) {
|
|
129
|
-
clippedViews.add(view)
|
|
130
|
-
view.clipToOutline = false
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Detect Fresco DraweeView and disable rounding
|
|
134
|
-
try {
|
|
135
|
-
val getHierarchy = view.javaClass.getMethod("getHierarchy")
|
|
136
|
-
val hierarchy = getHierarchy.invoke(view)
|
|
137
|
-
if (hierarchy != null) {
|
|
138
|
-
val getRounding = hierarchy.javaClass.getMethod("getRoundingParams")
|
|
139
|
-
val rounding = getRounding.invoke(hierarchy)
|
|
140
|
-
if (rounding != null) {
|
|
141
|
-
val roundingClass = Class.forName("com.facebook.drawee.generic.RoundingParams")
|
|
142
|
-
val setRounding = hierarchy.javaClass.getMethod("setRoundingParams", roundingClass)
|
|
143
|
-
setRounding.invoke(hierarchy, null)
|
|
144
|
-
frescoStates.add(FrescoState(view, hierarchy, rounding))
|
|
145
|
-
frescoViews[view] = hierarchy
|
|
146
|
-
Log.d(TAG, "captureSnapshot: disabled Fresco rounding on ${view.width}x${view.height}")
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
} catch (_: Exception) {}
|
|
150
|
-
|
|
151
|
-
if (view is ViewGroup) {
|
|
152
|
-
for (i in 0 until view.childCount) {
|
|
153
|
-
prepareView(view.getChildAt(i))
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
for (i in 0 until childCount) {
|
|
159
|
-
prepareView(getChildAt(i))
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Draw children. For Fresco views, draw the top-level drawable directly
|
|
163
|
-
// (since the internal drawable is rebuilt when roundingParams changes).
|
|
164
|
-
fun drawView(view: View, c: Canvas) {
|
|
165
|
-
val hierarchy = frescoViews[view]
|
|
166
|
-
if (hierarchy != null) {
|
|
167
|
-
try {
|
|
168
|
-
val getTopDrawable = hierarchy.javaClass.getMethod("getTopLevelDrawable")
|
|
169
|
-
val drawable = getTopDrawable.invoke(hierarchy) as? android.graphics.drawable.Drawable
|
|
170
|
-
if (drawable != null) {
|
|
171
|
-
drawable.setBounds(0, 0, view.width, view.height)
|
|
172
|
-
drawable.invalidateSelf()
|
|
173
|
-
drawable.draw(c)
|
|
174
|
-
Log.d(TAG, "captureSnapshot: drew Fresco drawable directly ${view.width}x${view.height}")
|
|
175
|
-
return
|
|
176
|
-
}
|
|
177
|
-
} catch (_: Exception) {}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (view is ViewGroup) {
|
|
181
|
-
// Draw background
|
|
182
|
-
view.background?.let { bg ->
|
|
183
|
-
bg.setBounds(0, 0, view.width, view.height)
|
|
184
|
-
bg.draw(c)
|
|
185
|
-
}
|
|
186
|
-
for (i in 0 until view.childCount) {
|
|
187
|
-
val child = view.getChildAt(i)
|
|
188
|
-
if (child.visibility != VISIBLE) continue
|
|
189
|
-
c.save()
|
|
190
|
-
c.translate(child.left.toFloat(), child.top.toFloat())
|
|
191
|
-
drawView(child, c)
|
|
192
|
-
c.restore()
|
|
193
|
-
}
|
|
194
|
-
} else {
|
|
195
|
-
view.draw(c)
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
108
|
for (i in 0 until childCount) {
|
|
200
109
|
val child = getChildAt(i)
|
|
201
110
|
if (child.visibility != VISIBLE) continue
|
|
202
111
|
canvas.save()
|
|
203
112
|
canvas.translate(child.left.toFloat(), child.top.toFloat())
|
|
204
|
-
|
|
113
|
+
child.draw(canvas)
|
|
205
114
|
canvas.restore()
|
|
206
115
|
}
|
|
207
|
-
|
|
208
|
-
// Restore clipToOutline
|
|
209
|
-
for (view in clippedViews) {
|
|
210
|
-
view.clipToOutline = true
|
|
211
|
-
}
|
|
212
|
-
// Restore Fresco rounding params
|
|
213
|
-
for (state in frescoStates) {
|
|
214
|
-
try {
|
|
215
|
-
val roundingClass = Class.forName("com.facebook.drawee.generic.RoundingParams")
|
|
216
|
-
val setRounding = state.hierarchy.javaClass.getMethod("setRoundingParams", roundingClass)
|
|
217
|
-
setRounding.invoke(state.hierarchy, state.roundingParams)
|
|
218
|
-
} catch (_: Exception) {}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
116
|
return bitmap
|
|
222
117
|
}
|
|
223
118
|
|
|
@@ -141,7 +141,8 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
141
141
|
return [renderer imageWithActions:^(UIGraphicsImageRendererContext *ctx) {
|
|
142
142
|
for (UIView *child in self.subviews) {
|
|
143
143
|
CGContextSaveGState(ctx.CGContext);
|
|
144
|
-
CGContextTranslateCTM(ctx.CGContext, child.frame.origin.x,
|
|
144
|
+
CGContextTranslateCTM(ctx.CGContext, child.frame.origin.x,
|
|
145
|
+
child.frame.origin.y);
|
|
145
146
|
[child drawViewHierarchyInRect:(CGRect){CGPointZero, child.frame.size}
|
|
146
147
|
afterScreenUpdates:NO];
|
|
147
148
|
CGContextRestoreGState(ctx.CGContext);
|
|
@@ -258,9 +259,7 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
258
259
|
UIView *ts = self->_targetScreenContainer;
|
|
259
260
|
if (ts) {
|
|
260
261
|
[UIView animateWithDuration:dur * 0.5
|
|
261
|
-
animations:^{
|
|
262
|
-
ts.alpha = 1;
|
|
263
|
-
}
|
|
262
|
+
animations:^{ ts.alpha = 1; }
|
|
264
263
|
completion:nil];
|
|
265
264
|
}
|
|
266
265
|
});
|
|
@@ -284,14 +283,8 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
284
283
|
self.alpha = 1;
|
|
285
284
|
UIView *ts = self->_targetScreenContainer;
|
|
286
285
|
if (ts) { ts.alpha = 1; }
|
|
287
|
-
[
|
|
288
|
-
|
|
289
|
-
wrapper.alpha = 0;
|
|
290
|
-
}
|
|
291
|
-
completion:^(BOOL finished) {
|
|
292
|
-
[wrapper removeFromSuperview];
|
|
293
|
-
self->_wrapperView = nil;
|
|
294
|
-
}];
|
|
286
|
+
[wrapper removeFromSuperview];
|
|
287
|
+
self->_wrapperView = nil;
|
|
295
288
|
resolve(@(YES));
|
|
296
289
|
}];
|
|
297
290
|
|
|
@@ -345,9 +338,7 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
345
338
|
UIView *ts = self->_targetScreenContainer;
|
|
346
339
|
if (ts) {
|
|
347
340
|
[UIView animateWithDuration:dur * 0.5
|
|
348
|
-
animations:^{
|
|
349
|
-
ts.alpha = 1;
|
|
350
|
-
}
|
|
341
|
+
animations:^{ ts.alpha = 1; }
|
|
351
342
|
completion:nil];
|
|
352
343
|
}
|
|
353
344
|
});
|
|
@@ -365,15 +356,9 @@ static CGRect imageFrameForScaleMode(UIViewContentMode mode,
|
|
|
365
356
|
self.alpha = 1;
|
|
366
357
|
UIView *ts = self->_targetScreenContainer;
|
|
367
358
|
if (ts) { ts.alpha = 1; }
|
|
368
|
-
[
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
372
|
-
completion:^(BOOL finished) {
|
|
373
|
-
[container removeFromSuperview];
|
|
374
|
-
self->_wrapperView = nil;
|
|
375
|
-
self->_snapshot = nil;
|
|
376
|
-
}];
|
|
359
|
+
[container removeFromSuperview];
|
|
360
|
+
self->_wrapperView = nil;
|
|
361
|
+
self->_snapshot = nil;
|
|
377
362
|
resolve(@(YES));
|
|
378
363
|
}];
|
|
379
364
|
|
package/package.json
CHANGED